Merge from vscode bd0efff9e3f36d6b3e1045cee9887003af8034d7

This commit is contained in:
ADS Merger
2020-05-06 02:35:49 +00:00
parent 9a7810cbee
commit 8420d9f04e
243 changed files with 4276 additions and 2478 deletions
+40
View File
@@ -0,0 +1,40 @@
name: "Classifier: Trainer"
on:
schedule:
- cron: 0 0 12 * *
jobs:
main:
runs-on: ubuntu-latest
steps:
- name: Checkout Actions
uses: actions/checkout@v2
with:
repository: 'microsoft/vscode-github-triage-actions'
ref: master
lfs: true
path: ./actions
- name: Install Actions
run: npm install --production --prefix ./actions
- name: Install Additional Dependencies
# Pulls in a bunch of other packages that arent needed for the rest of the actions
run: npm install @azure/storage-blob@12
- name: "Run Classifier: Scraper"
uses: ./actions/classifier/train/fetch-issues
with:
token: ${{secrets.ISSUE_SCRAPER_TOKEN}} # My personal token, so as to not risk going over quota on main token
- name: Set up Python 3.7
uses: actions/setup-python@v1
with:
python-version: 3.7
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install --upgrade numpy scipy scikit-learn joblib nltk
- name: "Run Classifier: Generator"
run: python ./actions/classifier/train/generate-models/generate.py category
- name: "Run Classifier: Upload"
uses: ./actions/classifier/train/upload-models
with:
blobContainerName: classifier-models
blobStorageKey: ${{secrets.AZURE_BLOB_STORAGE_CONNECTION_STRING}}
-6
View File
@@ -1,6 +0,0 @@
{
"useTabs": true,
"printWidth": 120,
"semi": true,
"singleQuote": true
}
+1 -1
View File
@@ -1,3 +1,3 @@
disturl "https://atom.io/download/electron"
target "7.2.2"
target "7.2.4"
runtime "electron"
+1 -1
View File
@@ -44,7 +44,7 @@ function prepareDebPackage(arch) {
.pipe(replace('@@NAME_SHORT@@', product.nameShort))
.pipe(replace('@@NAME@@', product.applicationName))
.pipe(replace('@@EXEC@@', `/usr/share/${product.applicationName}/${product.applicationName}`))
.pipe(replace('@@ICON@@', `/usr/share/pixmaps/${product.linuxIconName}.png`))
.pipe(replace('@@ICON@@', product.linuxIconName))
.pipe(replace('@@URLPROTOCOL@@', product.urlProtocol));
const appdata = gulp.src('resources/linux/code.appdata.xml', { base: '.' })
+1 -1
View File
@@ -48,7 +48,7 @@
"rollup-plugin-commonjs": "^10.1.0",
"rollup-plugin-node-resolve": "^5.2.0",
"terser": "4.3.8",
"typescript": "^3.9.0-dev.20200427",
"typescript": "^3.9.1-rc",
"vsce": "1.48.0",
"vscode-telemetry-extractor": "^1.5.4",
"xml2js": "^0.4.17"
+4 -4
View File
@@ -3462,10 +3462,10 @@ typescript@^3.0.1:
resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.5.3.tgz#c830f657f93f1ea846819e929092f5fe5983e977"
integrity sha512-ACzBtm/PhXBDId6a6sDJfroT2pOWt/oOnk4/dElG5G33ZL776N3Y6/6bKZJBFpd+b05F3Ct9qDjMeJmRWtE2/g==
typescript@^3.9.0-dev.20200427:
version "3.9.0-dev.20200427"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.9.0-dev.20200427.tgz#e42d606d938575dfb7b0b66f04a31b5f0eb0be57"
integrity sha512-ja/GhL7BHT+VQZiLoYMGJt2CP1Pdr0EhYefv4LLw4tVooSuCDB8SDKT/i/HwsoPgQ4ZaYfg1vPl+1RhiO3bwJg==
typescript@^3.9.1-rc:
version "3.9.1-rc"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.9.1-rc.tgz#81d5a5a0a597e224b6e2af8dffb46524b2eaf5f3"
integrity sha512-+cPv8L2Vd4KidCotqi2wjegBZ5n47CDRUu/QiLVu2YbeXAz78hIfcai9ziBiNI6JTGTVwUqXRug2UZxDcxhvFw==
typical@^4.0.0:
version "4.0.0"
+2 -2
View File
@@ -60,12 +60,12 @@
"git": {
"name": "electron",
"repositoryUrl": "https://github.com/electron/electron",
"commitHash": "959e80cc53cbebf8eb1d62eb2d14fa8fd86b0394"
"commitHash": "0552e0d5de46ffa3b481d741f1db5c779e201565"
}
},
"isOnlyProductionDependency": true,
"license": "MIT",
"version": "7.2.2"
"version": "7.2.4"
},
{
"component": {
@@ -282,33 +282,42 @@
]
}
},
"allOf": [
"oneOf": [
{
"oneOf": [
"allOf": [
{
"allOf": [
"oneOf": [
{
"oneOf": [
"allOf": [
{
"$ref": "#/definitions/dockerfileContainer"
"oneOf": [
{
"$ref": "#/definitions/dockerfileContainer"
},
{
"$ref": "#/definitions/imageContainer"
}
]
},
{
"$ref": "#/definitions/imageContainer"
"$ref": "#/definitions/nonComposeBase"
}
]
},
{
"$ref": "#/definitions/nonComposeBase"
"$ref": "#/definitions/composeContainer"
}
]
},
{
"$ref": "#/definitions/composeContainer"
"$ref": "#/definitions/devContainerCommon"
}
]
},
{
"$ref": "#/definitions/devContainerCommon"
"type": "object",
"$ref": "#/definitions/devContainerCommon",
"additionalProperties": false
}
]
}
@@ -133,7 +133,6 @@ export class MarkdownPreviewManager extends Disposable implements vscode.Webview
webview: vscode.WebviewPanel,
state: any
): Promise<void> {
console.log(state);
const resource = vscode.Uri.parse(state.resource);
const locked = state.locked;
const line = state.line;
+1 -1
View File
@@ -3,7 +3,7 @@
"version": "0.0.1",
"description": "Dependencies shared by all extensions",
"dependencies": {
"typescript": "3.8.3"
"typescript": "3.9.1-rc"
},
"scripts": {
"postinstall": "node ./postinstall"
+4 -4
View File
@@ -2,7 +2,7 @@
# yarn lockfile v1
typescript@3.8.3:
version "3.8.3"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.8.3.tgz#409eb8544ea0335711205869ec458ab109ee1061"
integrity sha512-MYlEfn5VrLNsgudQTVJeNaQFUAI7DkhnOjdpAp4T+ku1TfQClewlbSuTVHiA+8skNBgaf02TL/kLOvig4y3G8w==
typescript@3.9.1-rc:
version "3.9.1-rc"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.9.1-rc.tgz#81d5a5a0a597e224b6e2af8dffb46524b2eaf5f3"
integrity sha512-+cPv8L2Vd4KidCotqi2wjegBZ5n47CDRUu/QiLVu2YbeXAz78hIfcai9ziBiNI6JTGTVwUqXRug2UZxDcxhvFw==
+7 -7
View File
@@ -81,11 +81,11 @@
"vscode-ripgrep": "^1.5.8",
"vscode-sqlite3": "4.0.10",
"vscode-textmate": "5.1.1",
"xterm": "4.6.0-beta.25",
"xterm-addon-search": "0.6.0",
"xterm-addon-unicode11": "0.2.0-beta.2",
"xterm-addon-web-links": "0.3.0",
"xterm-addon-webgl": "0.7.0-beta.8",
"xterm": "4.6.0-beta.38",
"xterm-addon-search": "0.7.0-beta.2",
"xterm-addon-unicode11": "0.2.0-beta.5",
"xterm-addon-web-links": "0.4.0-beta.5",
"xterm-addon-webgl": "0.7.0-beta.10",
"yauzl": "^2.9.2",
"yazl": "^2.4.3",
"zone.js": "^0.8.4"
@@ -126,7 +126,7 @@
"css-loader": "^3.2.0",
"debounce": "^1.0.0",
"deemon": "^1.4.0",
"electron": "7.2.2",
"electron": "7.2.4",
"eslint": "6.8.0",
"eslint-plugin-jsdoc": "^19.1.0",
"event-stream": "3.3.4",
@@ -183,7 +183,7 @@
"temp-write": "^3.4.0",
"ts-loader": "^4.4.2",
"typemoq": "^0.3.2",
"typescript": "^3.9.0-dev.20200427",
"typescript": "^3.9.1-rc",
"typescript-formatter": "7.1.0",
"underscore": "^1.8.2",
"vinyl": "^2.0.0",
+5 -5
View File
@@ -38,11 +38,11 @@
"vscode-proxy-agent": "^0.5.2",
"vscode-ripgrep": "^1.5.8",
"vscode-textmate": "5.1.1",
"xterm": "4.6.0-beta.25",
"xterm-addon-search": "0.6.0",
"xterm-addon-unicode11": "0.2.0-beta.2",
"xterm-addon-web-links": "0.3.0",
"xterm-addon-webgl": "0.7.0-beta.8",
"xterm": "4.6.0-beta.38",
"xterm-addon-search": "0.7.0-beta.2",
"xterm-addon-unicode11": "0.2.0-beta.5",
"xterm-addon-web-links": "0.4.0-beta.5",
"xterm-addon-webgl": "0.7.0-beta.10",
"yauzl": "^2.9.2",
"yazl": "^2.4.3",
"zone.js": "^0.8.4"
+5 -5
View File
@@ -23,11 +23,11 @@
"slickgrid": "github:anthonydresser/SlickGrid#2.3.33",
"vscode-oniguruma": "1.3.0",
"vscode-textmate": "5.1.1",
"xterm": "4.6.0-beta.25",
"xterm-addon-search": "0.6.0",
"xterm-addon-unicode11": "0.2.0-beta.2",
"xterm-addon-web-links": "0.3.0",
"xterm-addon-webgl": "0.7.0-beta.8",
"xterm": "4.6.0-beta.38",
"xterm-addon-search": "0.7.0-beta.2",
"xterm-addon-unicode11": "0.2.0-beta.5",
"xterm-addon-web-links": "0.4.0-beta.5",
"xterm-addon-webgl": "0.7.0-beta.10",
"zone.js": "^0.8.4"
}
}
+20 -20
View File
@@ -353,30 +353,30 @@ xtend@^4.0.1:
resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54"
integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==
xterm-addon-search@0.6.0:
version "0.6.0"
resolved "https://registry.yarnpkg.com/xterm-addon-search/-/xterm-addon-search-0.6.0.tgz#542cc2c35e83e7332ce1982b65ad218ee769836c"
integrity sha512-k3EsZzUptCXygHFP5rQuCBdWWkI/ZNuX3pDSOVdxPV9jB7U5Aha9guTIZoMP7FIjL8jce+ClQs6q7VINcRV1+w==
xterm-addon-search@0.7.0-beta.2:
version "0.7.0-beta.2"
resolved "https://registry.yarnpkg.com/xterm-addon-search/-/xterm-addon-search-0.7.0-beta.2.tgz#384bda136c707f97a77eefc76cc7d9e572ce0719"
integrity sha512-A9fyiBBvG6ZNIwSJ03+sRCv9y20/uzd1wjCoaYUqp9fu3YGiHaGwyo9rAfm2M/fQM5vBmyJk4Qw/lwVq7TtlAw==
xterm-addon-unicode11@0.2.0-beta.2:
version "0.2.0-beta.2"
resolved "https://registry.yarnpkg.com/xterm-addon-unicode11/-/xterm-addon-unicode11-0.2.0-beta.2.tgz#2a13ba5b08fdb1005be241816c4e3302674db4af"
integrity sha512-Y047mnIWrAj65TpStdyPYoPeDTX4en+XX4Y90KuQB3cW2xIyZj25NSVV9BZdqzSb7gk9M6KBvIcm8chj7S2N8Q==
xterm-addon-unicode11@0.2.0-beta.5:
version "0.2.0-beta.5"
resolved "https://registry.yarnpkg.com/xterm-addon-unicode11/-/xterm-addon-unicode11-0.2.0-beta.5.tgz#5961850162df20b5e966166423cd6957ac2db298"
integrity sha512-IjnbBcyfS5JgJDXPO0W2nk/VBtGwx6GWE2snMC676z4DmAABUqPXfTzJKfUoWqoT6UcbxB0oIjDzykCfoRJp6Q==
xterm-addon-web-links@0.3.0:
version "0.3.0"
resolved "https://registry.yarnpkg.com/xterm-addon-web-links/-/xterm-addon-web-links-0.3.0.tgz#88affe9235c928b41bab660a65330f46d91c940e"
integrity sha512-vGXiIDqNMyxK5S1IzOjDqcgeQrrv7TDcSHiOeCNAoWCI2f+Rap9d18gjgnMKPyR+AbG0KoKnaKA6Dc1du1vs5A==
xterm-addon-web-links@0.4.0-beta.5:
version "0.4.0-beta.5"
resolved "https://registry.yarnpkg.com/xterm-addon-web-links/-/xterm-addon-web-links-0.4.0-beta.5.tgz#523fd0a1c5668370d73e05019ed16eaf596894c8"
integrity sha512-Qe0idPpSokCNvGrthSBjdrOZrsgXwnLYbzuv0JoEec/A9HVcxKmZ+ktw7fOA2gT/zbcwtrA5FWrir3GlRHglCQ==
xterm-addon-webgl@0.7.0-beta.8:
version "0.7.0-beta.8"
resolved "https://registry.yarnpkg.com/xterm-addon-webgl/-/xterm-addon-webgl-0.7.0-beta.8.tgz#546651958d740bf05d6a05555fbcacd2759b2ee7"
integrity sha512-2jxMtRR5zgAar1gPqt0iD/+GOlZ3cHyzzbIbC77EBIdZZFuhEDhJkucVPPS2KPcyqw3VROL1FgX7BSEV2rvdeA==
xterm-addon-webgl@0.7.0-beta.10:
version "0.7.0-beta.10"
resolved "https://registry.yarnpkg.com/xterm-addon-webgl/-/xterm-addon-webgl-0.7.0-beta.10.tgz#39fdb96351e97a1bf15f4c4c8944ba3d05cacee4"
integrity sha512-nQl/ASk+ck11aSrBZXb2a0tu+SNDnm89owBk/sAZeZzi5MHNo6bB8y2VTKNNC6D3i3aFouTz4VorYB25LUgNFg==
xterm@4.6.0-beta.25:
version "4.6.0-beta.25"
resolved "https://registry.yarnpkg.com/xterm/-/xterm-4.6.0-beta.25.tgz#2faea6cf8c677ed545792562165604ce7f314026"
integrity sha512-63FLAUdJ8Bw9SMgLU3/r353P1WAtLxupbfvfddi4nMcz1WEGRq07O1CbmJn/bKHHkJw7gQQw0n1I8xnjFlLlTA==
xterm@4.6.0-beta.38:
version "4.6.0-beta.38"
resolved "https://registry.yarnpkg.com/xterm/-/xterm-4.6.0-beta.38.tgz#8472b168941500c3071aba482c2b5c6040951ec7"
integrity sha512-Q+nOalMD1MDGOqXdtkGZmOQqbSBU+71vhlX2RBwQoSpJa1QBrKDAhSlN/J+/XvouvVEtCiEFDeacF4EufMEIMg==
zone.js@^0.8.4:
version "0.8.29"
+20 -20
View File
@@ -740,30 +740,30 @@ xtend@^4.0.1:
resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54"
integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==
xterm-addon-search@0.6.0:
version "0.6.0"
resolved "https://registry.yarnpkg.com/xterm-addon-search/-/xterm-addon-search-0.6.0.tgz#542cc2c35e83e7332ce1982b65ad218ee769836c"
integrity sha512-k3EsZzUptCXygHFP5rQuCBdWWkI/ZNuX3pDSOVdxPV9jB7U5Aha9guTIZoMP7FIjL8jce+ClQs6q7VINcRV1+w==
xterm-addon-search@0.7.0-beta.2:
version "0.7.0-beta.2"
resolved "https://registry.yarnpkg.com/xterm-addon-search/-/xterm-addon-search-0.7.0-beta.2.tgz#384bda136c707f97a77eefc76cc7d9e572ce0719"
integrity sha512-A9fyiBBvG6ZNIwSJ03+sRCv9y20/uzd1wjCoaYUqp9fu3YGiHaGwyo9rAfm2M/fQM5vBmyJk4Qw/lwVq7TtlAw==
xterm-addon-unicode11@0.2.0-beta.2:
version "0.2.0-beta.2"
resolved "https://registry.yarnpkg.com/xterm-addon-unicode11/-/xterm-addon-unicode11-0.2.0-beta.2.tgz#2a13ba5b08fdb1005be241816c4e3302674db4af"
integrity sha512-Y047mnIWrAj65TpStdyPYoPeDTX4en+XX4Y90KuQB3cW2xIyZj25NSVV9BZdqzSb7gk9M6KBvIcm8chj7S2N8Q==
xterm-addon-unicode11@0.2.0-beta.5:
version "0.2.0-beta.5"
resolved "https://registry.yarnpkg.com/xterm-addon-unicode11/-/xterm-addon-unicode11-0.2.0-beta.5.tgz#5961850162df20b5e966166423cd6957ac2db298"
integrity sha512-IjnbBcyfS5JgJDXPO0W2nk/VBtGwx6GWE2snMC676z4DmAABUqPXfTzJKfUoWqoT6UcbxB0oIjDzykCfoRJp6Q==
xterm-addon-web-links@0.3.0:
version "0.3.0"
resolved "https://registry.yarnpkg.com/xterm-addon-web-links/-/xterm-addon-web-links-0.3.0.tgz#88affe9235c928b41bab660a65330f46d91c940e"
integrity sha512-vGXiIDqNMyxK5S1IzOjDqcgeQrrv7TDcSHiOeCNAoWCI2f+Rap9d18gjgnMKPyR+AbG0KoKnaKA6Dc1du1vs5A==
xterm-addon-web-links@0.4.0-beta.5:
version "0.4.0-beta.5"
resolved "https://registry.yarnpkg.com/xterm-addon-web-links/-/xterm-addon-web-links-0.4.0-beta.5.tgz#523fd0a1c5668370d73e05019ed16eaf596894c8"
integrity sha512-Qe0idPpSokCNvGrthSBjdrOZrsgXwnLYbzuv0JoEec/A9HVcxKmZ+ktw7fOA2gT/zbcwtrA5FWrir3GlRHglCQ==
xterm-addon-webgl@0.7.0-beta.8:
version "0.7.0-beta.8"
resolved "https://registry.yarnpkg.com/xterm-addon-webgl/-/xterm-addon-webgl-0.7.0-beta.8.tgz#546651958d740bf05d6a05555fbcacd2759b2ee7"
integrity sha512-2jxMtRR5zgAar1gPqt0iD/+GOlZ3cHyzzbIbC77EBIdZZFuhEDhJkucVPPS2KPcyqw3VROL1FgX7BSEV2rvdeA==
xterm-addon-webgl@0.7.0-beta.10:
version "0.7.0-beta.10"
resolved "https://registry.yarnpkg.com/xterm-addon-webgl/-/xterm-addon-webgl-0.7.0-beta.10.tgz#39fdb96351e97a1bf15f4c4c8944ba3d05cacee4"
integrity sha512-nQl/ASk+ck11aSrBZXb2a0tu+SNDnm89owBk/sAZeZzi5MHNo6bB8y2VTKNNC6D3i3aFouTz4VorYB25LUgNFg==
xterm@4.6.0-beta.25:
version "4.6.0-beta.25"
resolved "https://registry.yarnpkg.com/xterm/-/xterm-4.6.0-beta.25.tgz#2faea6cf8c677ed545792562165604ce7f314026"
integrity sha512-63FLAUdJ8Bw9SMgLU3/r353P1WAtLxupbfvfddi4nMcz1WEGRq07O1CbmJn/bKHHkJw7gQQw0n1I8xnjFlLlTA==
xterm@4.6.0-beta.38:
version "4.6.0-beta.38"
resolved "https://registry.yarnpkg.com/xterm/-/xterm-4.6.0-beta.38.tgz#8472b168941500c3071aba482c2b5c6040951ec7"
integrity sha512-Q+nOalMD1MDGOqXdtkGZmOQqbSBU+71vhlX2RBwQoSpJa1QBrKDAhSlN/J+/XvouvVEtCiEFDeacF4EufMEIMg==
yauzl@^2.9.2:
version "2.10.0"
Regular → Executable
View File
+1 -1
View File
@@ -55,7 +55,7 @@ function code() {
function code-wsl()
{
HOST_IP=$(powershell.exe -Command "& {(Get-NetIPAddress | Where-Object {\$_.InterfaceAlias -like '*WSL*' -and \$_.AddressFamily -eq 'IPv4'}).IPAddress | Write-Host -NoNewline}")
HOST_IP=$(powershell.exe noprofile -Command "& {(Get-NetIPAddress | Where-Object {\$_.InterfaceAlias -like '*WSL*' -and \$_.AddressFamily -eq 'IPv4'}).IPAddress | Write-Host -NoNewline}")
export DISPLAY="$HOST_IP:0"
# in a wsl shell
@@ -165,7 +165,7 @@ export class ExtHostTreeView<T> extends vsTreeExt.ExtHostTreeView<T> {
});
}
protected createTreeNode(element: T, extensionTreeItem: azdata.TreeComponentItem, parent?: vsTreeExt.TreeNode): vsTreeExt.TreeNode {
protected createTreeNode(element: T, extensionTreeItem: azdata.TreeComponentItem, parent?: vsTreeExt.TreeNode | vsTreeExt.Root): vsTreeExt.TreeNode {
let node = super.createTreeNode(element, extensionTreeItem, parent);
if (node.item) {
node.item = assign(node.item, { checked: extensionTreeItem.checked, enabled: extensionTreeItem.enabled });
@@ -5,9 +5,8 @@
import 'vs/css!./media/dataExplorer.contribution';
import { localize } from 'vs/nls';
import { ViewletRegistry, Extensions as ViewletExtensions } from 'vs/workbench/browser/viewlet';
import { Registry } from 'vs/platform/registry/common/platform';
import { DataExplorerViewletViewsContribution, OpenDataExplorerViewletAction, VIEWLET_ID } from 'sql/workbench/contrib/dataExplorer/browser/dataExplorerViewlet';
import { DataExplorerViewletViewsContribution, OpenDataExplorerViewletAction } from 'sql/workbench/contrib/dataExplorer/browser/dataExplorerViewlet';
import { IWorkbenchActionRegistry, Extensions as ActionExtensions } from 'vs/workbench/common/actions';
import { IWorkbenchContributionsRegistry, Extensions as WorkbenchExtensions } from 'vs/workbench/common/contributions';
import { LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle';
@@ -16,7 +15,6 @@ import { SyncActionDescriptor } from 'vs/platform/actions/common/actions';
import { KeyMod, KeyCode } from 'vs/base/common/keyCodes';
import { DataExplorerContainerExtensionHandler } from 'sql/workbench/contrib/dataExplorer/browser/dataExplorerExtensionPoint';
Registry.as<ViewletRegistry>(ViewletExtensions.Viewlets).setDefaultViewletId(VIEWLET_ID);
const workbenchRegistry = Registry.as<IWorkbenchContributionsRegistry>(WorkbenchExtensions.Workbench);
workbenchRegistry.registerWorkbenchContribution(DataExplorerViewletViewsContribution, LifecyclePhase.Starting);
const registry = Registry.as<IWorkbenchActionRegistry>(ActionExtensions.WorkbenchActions);
@@ -159,4 +159,4 @@ export const VIEW_CONTAINER = Registry.as<IViewContainersRegistry>(ViewContainer
icon: 'dataExplorer',
order: 0,
storageId: `${VIEWLET_ID}.state`
}, ViewContainerLocation.Sidebar);
}, ViewContainerLocation.Sidebar, true);
@@ -31,9 +31,10 @@ import { TestCapabilitiesService } from 'sql/platform/capabilities/test/common/t
import { UNSAVED_GROUP_ID, mssqlProviderName } from 'sql/platform/connection/common/constants';
import { $ } from 'vs/base/browser/dom';
import { OEManageConnectionAction } from 'sql/workbench/contrib/dashboard/browser/dashboardActions';
import { IViewsService, IView } from 'vs/workbench/common/views';
import { IViewsService, IView, ViewContainerLocation, ViewContainer } from 'vs/workbench/common/views';
import { ConsoleLogService } from 'vs/platform/log/common/log';
import { IProgressIndicator } from 'vs/platform/progress/common/progress';
import { IPaneComposite } from 'vs/workbench/common/panecomposite';
suite('SQL Connection Tree Action tests', () => {
let errorMessageService: TypeMoq.Mock<TestErrorMessageService>;
@@ -110,6 +111,22 @@ suite('SQL Connection Tree Action tests', () => {
});
const viewsService = new class implements IViewsService {
getViewProgressIndicator(id: string): IProgressIndicator {
throw new Error('Method not implemented.');
}
onDidChangeViewContainerVisibility: Event<{ id: string; visible: boolean; location: ViewContainerLocation; }>;
isViewContainerVisible(id: string): boolean {
throw new Error('Method not implemented.');
}
openViewContainer(id: string, focus?: boolean): Promise<IPaneComposite> {
throw new Error('Method not implemented.');
}
closeViewContainer(id: string): void {
throw new Error('Method not implemented.');
}
getVisibleViewContainer(location: ViewContainerLocation): ViewContainer {
throw new Error('Method not implemented.');
}
getProgressIndicator(id: string): IProgressIndicator {
throw new Error('Method not implemented.');
}
@@ -230,10 +230,10 @@ export class BreadcrumbsWidget {
for (let i = 0; i < this._nodes.length; i++) {
const node = this._nodes[i];
if (i !== nth) {
dom.removeClass(node, 'focused');
node.classList.remove('focused');
} else {
this._focusedItemIdx = i;
dom.addClass(node, 'focused');
node.classList.add('focused');
node.focus();
}
}
@@ -274,10 +274,10 @@ export class BreadcrumbsWidget {
for (let i = 0; i < this._nodes.length; i++) {
const node = this._nodes[i];
if (i !== nth) {
dom.removeClass(node, 'selected');
node.classList.remove('selected');
} else {
this._selectedItemIdx = i;
dom.addClass(node, 'selected');
node.classList.add('selected');
}
}
this._onDidSelectItem.fire({ type: 'select', item: this._items[this._selectedItemIdx], node: this._nodes[this._selectedItemIdx], payload });
+4
View File
@@ -10,6 +10,10 @@ export namespace Iterable {
return _empty;
}
export function* single<T>(element: T): Iterable<T> {
yield element;
}
export function from<T>(iterable: Iterable<T> | undefined | null): Iterable<T> {
return iterable || _empty;
}
+66 -39
View File
@@ -481,7 +481,9 @@ export class TernarySearchTree<K, V> {
}
}
export class ResourceMap<T> {
export class ResourceMap<T> implements Map<URI, T> {
readonly [Symbol.toStringTag] = 'ResourceMap';
protected readonly map: Map<string, T>;
protected readonly ignoreCase?: boolean;
@@ -491,8 +493,9 @@ export class ResourceMap<T> {
this.ignoreCase = false; // in the future this should be an uri-comparator
}
set(resource: URI, value: T): void {
set(resource: URI, value: T): this {
this.map.set(this.toKey(resource), value);
return this;
}
get(resource: URI): T | undefined {
@@ -515,12 +518,35 @@ export class ResourceMap<T> {
return this.map.delete(this.toKey(resource));
}
forEach(clb: (value: T, key: URI) => void): void {
this.map.forEach((value, index) => clb(value, URI.parse(index)));
forEach(clb: (value: T, key: URI, map: Map<URI, T>) => void, thisArg?: any): void {
if (typeof thisArg !== 'undefined') {
clb = clb.bind(thisArg);
}
for (let [index, value] of this.map) {
clb(value, URI.parse(index), <any>this);
}
}
values(): T[] {
return values(this.map);
values(): IterableIterator<T> {
return this.map.values();
}
*keys(): IterableIterator<URI> {
for (let key of this.map.keys()) {
yield URI.parse(key);
}
}
*entries(): IterableIterator<[URI, T]> {
for (let tuple of this.map.entries()) {
yield [URI.parse(tuple[0]), tuple[1]];
}
}
*[Symbol.iterator](): IterableIterator<[URI, T]> {
for (let item of this.map) {
yield [URI.parse(item[0]), item[1]];
}
}
private toKey(resource: URI): string {
@@ -532,10 +558,6 @@ export class ResourceMap<T> {
return key;
}
keys(): URI[] {
return keys(this.map).map(k => URI.parse(k));
}
clone(): ResourceMap<T> {
const resourceMap = new ResourceMap<T>();
@@ -558,7 +580,9 @@ export const enum Touch {
AsNew = 2
}
export class LinkedMap<K, V> {
export class LinkedMap<K, V> implements Map<K, V>{
readonly [Symbol.toStringTag] = 'LinkedMap';
private _map: Map<K, Item<K, V>>;
private _head: Item<K, V> | undefined;
@@ -610,7 +634,7 @@ export class LinkedMap<K, V> {
return item.value;
}
set(key: K, value: V, touch: Touch = Touch.None): void {
set(key: K, value: V, touch: Touch = Touch.None): this {
let item = this._map.get(key);
if (item) {
item.value = value;
@@ -636,6 +660,7 @@ export class LinkedMap<K, V> {
this._map.set(key, item);
this._size++;
}
return this;
}
delete(key: K): boolean {
@@ -679,34 +704,13 @@ export class LinkedMap<K, V> {
}
}
values(): V[] {
const result: V[] = [];
let current = this._head;
while (current) {
result.push(current.value);
current = current.next;
}
return result;
}
keys(): K[] {
const result: K[] = [];
let current = this._head;
while (current) {
result.push(current.key);
current = current.next;
}
return result;
}
/* VS Code / Monaco editor runs on es5 which has no Symbol.iterator
keys(): IterableIterator<K> {
const current = this._head;
let current = this._head;
const iterator: IterableIterator<K> = {
[Symbol.iterator]() {
return iterator;
},
next():IteratorResult<K> {
next(): IteratorResult<K> {
if (current) {
const result = { value: current.key, done: false };
current = current.next;
@@ -720,12 +724,12 @@ export class LinkedMap<K, V> {
}
values(): IterableIterator<V> {
const current = this._head;
let current = this._head;
const iterator: IterableIterator<V> = {
[Symbol.iterator]() {
return iterator;
},
next():IteratorResult<V> {
next(): IteratorResult<V> {
if (current) {
const result = { value: current.value, done: false };
current = current.next;
@@ -737,7 +741,29 @@ export class LinkedMap<K, V> {
};
return iterator;
}
*/
entries(): IterableIterator<[K, V]> {
let current = this._head;
const iterator: IterableIterator<[K, V]> = {
[Symbol.iterator]() {
return iterator;
},
next(): IteratorResult<[K, V]> {
if (current) {
const result: IteratorResult<[K, V]> = { value: [current.key, current.value], done: false };
current = current.next;
return result;
} else {
return { value: undefined, done: true };
}
}
};
return iterator;
}
[Symbol.iterator](): IterableIterator<[K, V]> {
return this.entries();
}
protected trimOld(newSize: number) {
if (newSize >= this.size) {
@@ -939,9 +965,10 @@ export class LRUCache<K, V> extends LinkedMap<K, V> {
return super.get(key, Touch.None);
}
set(key: K, value: V): void {
set(key: K, value: V): this {
super.set(key, value, Touch.AsNew);
this.checkTrim();
return this;
}
private checkTrim() {
@@ -274,8 +274,10 @@ class QuickInput extends Disposable implements IQuickInput {
return;
}
const title = this.getTitle();
if (this.ui.title.textContent !== title) {
if (title && this.ui.title.textContent !== title) {
this.ui.title.textContent = title;
} else if (!title && this.ui.title.innerHTML !== '&nbsp;') {
this.ui.title.innerHTML = '&nbsp;';
}
const description = this.getDescription();
if (this.ui.description.textContent !== description) {
+37 -32
View File
@@ -13,8 +13,8 @@ suite('Map', () => {
let map = new LinkedMap<string, string>();
map.set('ak', 'av');
map.set('bk', 'bv');
assert.deepStrictEqual(map.keys(), ['ak', 'bk']);
assert.deepStrictEqual(map.values(), ['av', 'bv']);
assert.deepStrictEqual([...map.keys()], ['ak', 'bk']);
assert.deepStrictEqual([...map.values()], ['av', 'bv']);
assert.equal(map.first, 'av');
assert.equal(map.last, 'bv');
});
@@ -23,16 +23,16 @@ suite('Map', () => {
let map = new LinkedMap<string, string>();
map.set('ak', 'av');
map.set('ak', 'av', Touch.AsOld);
assert.deepStrictEqual(map.keys(), ['ak']);
assert.deepStrictEqual(map.values(), ['av']);
assert.deepStrictEqual([...map.keys()], ['ak']);
assert.deepStrictEqual([...map.values()], ['av']);
});
test('LinkedMap - Touch New one', () => {
let map = new LinkedMap<string, string>();
map.set('ak', 'av');
map.set('ak', 'av', Touch.AsNew);
assert.deepStrictEqual(map.keys(), ['ak']);
assert.deepStrictEqual(map.values(), ['av']);
assert.deepStrictEqual([...map.keys()], ['ak']);
assert.deepStrictEqual([...map.values()], ['av']);
});
test('LinkedMap - Touch Old two', () => {
@@ -40,8 +40,8 @@ suite('Map', () => {
map.set('ak', 'av');
map.set('bk', 'bv');
map.set('bk', 'bv', Touch.AsOld);
assert.deepStrictEqual(map.keys(), ['bk', 'ak']);
assert.deepStrictEqual(map.values(), ['bv', 'av']);
assert.deepStrictEqual([...map.keys()], ['bk', 'ak']);
assert.deepStrictEqual([...map.values()], ['bv', 'av']);
});
test('LinkedMap - Touch New two', () => {
@@ -49,8 +49,8 @@ suite('Map', () => {
map.set('ak', 'av');
map.set('bk', 'bv');
map.set('ak', 'av', Touch.AsNew);
assert.deepStrictEqual(map.keys(), ['bk', 'ak']);
assert.deepStrictEqual(map.values(), ['bv', 'av']);
assert.deepStrictEqual([...map.keys()], ['bk', 'ak']);
assert.deepStrictEqual([...map.values()], ['bv', 'av']);
});
test('LinkedMap - Touch Old from middle', () => {
@@ -59,8 +59,8 @@ suite('Map', () => {
map.set('bk', 'bv');
map.set('ck', 'cv');
map.set('bk', 'bv', Touch.AsOld);
assert.deepStrictEqual(map.keys(), ['bk', 'ak', 'ck']);
assert.deepStrictEqual(map.values(), ['bv', 'av', 'cv']);
assert.deepStrictEqual([...map.keys()], ['bk', 'ak', 'ck']);
assert.deepStrictEqual([...map.values()], ['bv', 'av', 'cv']);
});
test('LinkedMap - Touch New from middle', () => {
@@ -69,8 +69,8 @@ suite('Map', () => {
map.set('bk', 'bv');
map.set('ck', 'cv');
map.set('bk', 'bv', Touch.AsNew);
assert.deepStrictEqual(map.keys(), ['ak', 'ck', 'bk']);
assert.deepStrictEqual(map.values(), ['av', 'cv', 'bv']);
assert.deepStrictEqual([...map.keys()], ['ak', 'ck', 'bk']);
assert.deepStrictEqual([...map.values()], ['av', 'cv', 'bv']);
});
test('LinkedMap - basics', function () {
@@ -136,13 +136,15 @@ suite('Map', () => {
assert.strictEqual(cache.size, 5);
cache.set(6, 6);
assert.strictEqual(cache.size, 5);
assert.deepStrictEqual(cache.keys(), [2, 3, 4, 5, 6]);
assert.deepStrictEqual([...cache.keys()], [2, 3, 4, 5, 6]);
cache.set(7, 7);
assert.strictEqual(cache.size, 5);
assert.deepStrictEqual(cache.keys(), [3, 4, 5, 6, 7]);
assert.deepStrictEqual([...cache.keys()], [3, 4, 5, 6, 7]);
let values: number[] = [];
[3, 4, 5, 6, 7].forEach(key => values.push(cache.get(key)!));
assert.deepStrictEqual(values, [3, 4, 5, 6, 7]);
assert.deepEqual([...cache.entries()], [[3, 3], [4, 4], [5, 5], [6, 6], [7, 7]]);
});
test('LinkedMap - LRU Cache get', () => {
@@ -150,11 +152,11 @@ suite('Map', () => {
[1, 2, 3, 4, 5].forEach(value => cache.set(value, value));
assert.strictEqual(cache.size, 5);
assert.deepStrictEqual(cache.keys(), [1, 2, 3, 4, 5]);
assert.deepStrictEqual([...cache.keys()], [1, 2, 3, 4, 5]);
cache.get(3);
assert.deepStrictEqual(cache.keys(), [1, 2, 4, 5, 3]);
assert.deepStrictEqual([...cache.keys()], [1, 2, 4, 5, 3]);
cache.peek(4);
assert.deepStrictEqual(cache.keys(), [1, 2, 4, 5, 3]);
assert.deepStrictEqual([...cache.keys()], [1, 2, 4, 5, 3]);
let values: number[] = [];
[1, 2, 3, 4, 5].forEach(key => values.push(cache.get(key)!));
assert.deepStrictEqual(values, [1, 2, 3, 4, 5]);
@@ -169,7 +171,7 @@ suite('Map', () => {
assert.strictEqual(cache.size, 10);
cache.limit = 5;
assert.strictEqual(cache.size, 5);
assert.deepStrictEqual(cache.keys(), [6, 7, 8, 9, 10]);
assert.deepStrictEqual([...cache.keys()], [6, 7, 8, 9, 10]);
cache.limit = 20;
assert.strictEqual(cache.size, 5);
for (let i = 11; i <= 20; i++) {
@@ -181,7 +183,7 @@ suite('Map', () => {
values.push(cache.get(i)!);
assert.strictEqual(cache.get(i), i);
}
assert.deepStrictEqual(cache.values(), values);
assert.deepStrictEqual([...cache.values()], values);
});
test('LinkedMap - LRU Cache limit with ratio', () => {
@@ -193,11 +195,11 @@ suite('Map', () => {
assert.strictEqual(cache.size, 10);
cache.set(11, 11);
assert.strictEqual(cache.size, 5);
assert.deepStrictEqual(cache.keys(), [7, 8, 9, 10, 11]);
assert.deepStrictEqual([...cache.keys()], [7, 8, 9, 10, 11]);
let values: number[] = [];
cache.keys().forEach(key => values.push(cache.get(key)!));
[...cache.keys()].forEach(key => values.push(cache.get(key)!));
assert.deepStrictEqual(values, [7, 8, 9, 10, 11]);
assert.deepStrictEqual(cache.values(), values);
assert.deepStrictEqual([...cache.values()], values);
});
test('LinkedMap - toJSON / fromJSON', () => {
@@ -237,7 +239,7 @@ suite('Map', () => {
map.delete('1');
assert.equal(map.get('1'), undefined);
assert.equal(map.size, 0);
assert.equal(map.keys().length, 0);
assert.equal([...map.keys()].length, 0);
});
test('LinkedMap - delete Head', function () {
@@ -251,8 +253,8 @@ suite('Map', () => {
map.delete('1');
assert.equal(map.get('2'), 2);
assert.equal(map.size, 1);
assert.equal(map.keys().length, 1);
assert.equal(map.keys()[0], 2);
assert.equal([...map.keys()].length, 1);
assert.equal([...map.keys()][0], 2);
});
test('LinkedMap - delete Tail', function () {
@@ -266,8 +268,8 @@ suite('Map', () => {
map.delete('2');
assert.equal(map.get('1'), 1);
assert.equal(map.size, 1);
assert.equal(map.keys().length, 1);
assert.equal(map.keys()[0], 1);
assert.equal([...map.keys()].length, 1);
assert.equal([...map.keys()][0], 1);
});
@@ -656,18 +658,21 @@ suite('Map', () => {
assert.equal(map.size, 0);
map.set(resource1, 1);
let res = map.set(resource1, 1);
assert.ok(res === map);
map.set(resource2, '2');
map.set(resource3, true);
const values = map.values();
const values = [...map.values()];
assert.equal(values[0], 1);
assert.equal(values[1], '2');
assert.equal(values[2], true);
let counter = 0;
map.forEach(value => {
map.forEach((value, key, mapObj) => {
assert.equal(value, values[counter++]);
assert.ok(URI.isUri(key));
assert.ok(map === mapObj);
});
const obj = Object.create(null);
+2 -2
View File
@@ -502,7 +502,7 @@ export class CodeWindow extends Disposable implements ICodeWindow {
}
private onWindowError(error: WindowError): void {
this.logService.error(error === WindowError.CRASHED ? '[VS Code]: render process crashed!' : '[VS Code]: detected unresponsive');
this.logService.error(error === WindowError.CRASHED ? '[VS Code]: renderer process crashed!' : '[VS Code]: detected unresponsive');
// If we run extension tests from CLI, showing a dialog is not
// very helpful in this case. Rather, we bring down the test run
@@ -937,7 +937,7 @@ export class CodeWindow extends Disposable implements ICodeWindow {
// Multi Montior (fullscreen): try to find the previously used display
if (state.display && state.mode === WindowMode.Fullscreen) {
const display = displays.filter(d => d.id === state.display)[0];
const display = displays.find(d => d.id === state.display);
if (display && typeof display.bounds?.x === 'number' && typeof display.bounds?.y === 'number') {
this.logService.trace('window#validateWindowState: restoring fullscreen to previous display');
+1 -1
View File
@@ -216,7 +216,7 @@ export class Main {
const extensionIdentifier = { id: getGalleryExtensionId(manifest.publisher, manifest.name) };
const installedExtensions = await this.extensionManagementService.getInstalled(ExtensionType.User);
const newer = installedExtensions.filter(local => areSameExtensions(extensionIdentifier, local.identifier) && semver.gt(local.manifest.version, manifest.version))[0];
const newer = installedExtensions.find(local => areSameExtensions(extensionIdentifier, local.identifier) && semver.gt(local.manifest.version, manifest.version));
if (newer && !force) {
console.log(localize('forceDowngrade', "A newer version of extension '{0}' v{1} is already installed. Use '--force' option to downgrade to older version.", newer.identifier.id, newer.manifest.version, manifest.version));
+14 -2
View File
@@ -156,12 +156,13 @@ export class StableEditorScrollState {
visiblePositionScrollDelta = editor.getScrollTop() - visiblePositionScrollTop;
}
}
return new StableEditorScrollState(visiblePosition, visiblePositionScrollDelta);
return new StableEditorScrollState(visiblePosition, visiblePositionScrollDelta, editor.getPosition());
}
constructor(
private readonly _visiblePosition: Position | null,
private readonly _visiblePositionScrollDelta: number
private readonly _visiblePositionScrollDelta: number,
private readonly _cursorPosition: Position | null
) {
}
@@ -171,4 +172,15 @@ export class StableEditorScrollState {
editor.setScrollTop(visiblePositionScrollTop + this._visiblePositionScrollDelta);
}
}
public restoreRelativeVerticalPositionOfCursor(editor: ICodeEditor): void {
const currentCursorPosition = editor.getPosition();
if (!this._cursorPosition || !currentCursorPosition) {
return;
}
const offset = editor.getTopForLineNumber(currentCursorPosition.lineNumber) - editor.getTopForLineNumber(this._cursorPosition.lineNumber);
editor.setScrollTop(editor.getScrollTop() + offset);
}
}
@@ -21,6 +21,8 @@ import { IKeybindings, KeybindingsRegistry } from 'vs/platform/keybinding/common
import { Registry } from 'vs/platform/registry/common/platform';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { withNullAsUndefined, assertType } from 'vs/base/common/types';
import { ThemeIcon } from 'vs/platform/theme/common/themeService';
export type ServicesAccessor = InstantiationServicesAccessor;
export type IEditorContributionCtor = IConstructorSignature1<ICodeEditor, IEditorContribution>;
@@ -48,6 +50,7 @@ export interface ICommandMenuOptions {
order: number;
when?: ContextKeyExpression;
title: string;
icon?: ThemeIcon
}
export interface ICommandOptions {
id: string;
@@ -118,6 +121,7 @@ export abstract class Command {
command: {
id: this.id,
title: item.title,
icon: item.icon
// precondition: this.precondition
},
when: item.when,
@@ -1804,7 +1804,7 @@ export class EditorModeContext extends Disposable {
this._hasDocumentSelectionFormattingProvider = EditorContextKeys.hasDocumentSelectionFormattingProvider.bindTo(_contextKeyService);
this._hasMultipleDocumentFormattingProvider = EditorContextKeys.hasMultipleDocumentFormattingProvider.bindTo(_contextKeyService);
this._hasMultipleDocumentSelectionFormattingProvider = EditorContextKeys.hasMultipleDocumentSelectionFormattingProvider.bindTo(_contextKeyService);
this._isInWalkThrough = EditorContextKeys.isInEmbeddedEditor.bindTo(_contextKeyService);
this._isInWalkThrough = EditorContextKeys.isInWalkThroughSnippet.bindTo(_contextKeyService);
const update = () => this._update();
+8 -1
View File
@@ -32,10 +32,17 @@ export namespace EditorContextKeys {
export const hasSingleSelection = hasMultipleSelections.toNegated();
export const tabMovesFocus = new RawContextKey<boolean>('editorTabMovesFocus', false);
export const tabDoesNotMoveFocus = tabMovesFocus.toNegated();
export const isInEmbeddedEditor = new RawContextKey<boolean>('isInEmbeddedEditor', false);
export const isInWalkThroughSnippet = new RawContextKey<boolean>('isInEmbeddedEditor', false);
export const canUndo = new RawContextKey<boolean>('canUndo', false);
export const canRedo = new RawContextKey<boolean>('canRedo', false);
/**
* A context key that is set when an editor is part of a larger editor, like notebooks or
* (future) a diff editor
*/
export const inCompositeEditor = new RawContextKey<boolean>('inCompositeEditor', undefined);
export const notInCompositeEditor = inCompositeEditor.toNegated();
// -- mode context keys
export const languageId = new RawContextKey<string>('editorLangId', '');
export const hasCompletionItemProvider = new RawContextKey<boolean>('editorHasCompletionItemProvider', false);
+9 -2
View File
@@ -3,6 +3,7 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { Event } from 'vs/base/common/event';
import { IMarkdownString } from 'vs/base/common/htmlContent';
import { IDisposable } from 'vs/base/common/lifecycle';
import { URI } from 'vs/base/common/uri';
@@ -1276,7 +1277,8 @@ export class ValidAnnotatedEditOperation implements IIdentifiedSingleEditOperati
/**
* @internal
*/
export interface ITextBuffer {
export interface IReadonlyTextBuffer {
onDidChangeContent: Event<void>;
equals(other: ITextBuffer): boolean;
mightContainRTL(): boolean;
mightContainNonBasicASCII(): boolean;
@@ -1299,10 +1301,15 @@ export interface ITextBuffer {
getLineLength(lineNumber: number): number;
getLineFirstNonWhitespaceColumn(lineNumber: number): number;
getLineLastNonWhitespaceColumn(lineNumber: number): number;
findMatchesLineByLine(searchRange: Range, searchData: SearchData, captureMatches: boolean, limitResultCount: number): FindMatch[];
}
/**
* @internal
*/
export interface ITextBuffer extends IReadonlyTextBuffer {
setEOL(newEOL: '\r\n' | '\n'): void;
applyEdits(rawOperations: ValidAnnotatedEditOperation[], recordTrimAutoWhitespace: boolean, computeUndoEdits: boolean): ApplyEditsResult;
findMatchesLineByLine(searchRange: Range, searchData: SearchData, captureMatches: boolean, limitResultCount: number): FindMatch[];
}
/**
@@ -3,6 +3,7 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { Emitter, Event } from 'vs/base/common/event';
import * as strings from 'vs/base/common/strings';
import { Position } from 'vs/editor/common/core/position';
import { Range } from 'vs/editor/common/core/range';
@@ -11,6 +12,7 @@ import { PieceTreeBase, StringBuffer } from 'vs/editor/common/model/pieceTreeTex
import { SearchData } from 'vs/editor/common/model/textModelSearch';
import { countEOL, StringEOL } from 'vs/editor/common/model/tokensStore';
import { TextChange } from 'vs/editor/common/model/textChange';
import { IDisposable } from 'vs/base/common/lifecycle';
export interface IValidatedEditOperation {
sortIndex: number;
@@ -30,18 +32,24 @@ export interface IReverseSingleEditOperation extends IValidEditOperation {
sortIndex: number;
}
export class PieceTreeTextBuffer implements ITextBuffer {
export class PieceTreeTextBuffer implements ITextBuffer, IDisposable {
private readonly _pieceTree: PieceTreeBase;
private readonly _BOM: string;
private _mightContainRTL: boolean;
private _mightContainNonBasicASCII: boolean;
private readonly _onDidChangeContent: Emitter<void> = new Emitter<void>();
public readonly onDidChangeContent: Event<void> = this._onDidChangeContent.event;
constructor(chunks: StringBuffer[], BOM: string, eol: '\r\n' | '\n', containsRTL: boolean, isBasicASCII: boolean, eolNormalized: boolean) {
this._BOM = BOM;
this._mightContainNonBasicASCII = !isBasicASCII;
this._mightContainRTL = containsRTL;
this._pieceTree = new PieceTreeBase(chunks, eol, eolNormalized);
}
dispose(): void {
this._onDidChangeContent.dispose();
}
// #region TextBuffer
public equals(other: ITextBuffer): boolean {
@@ -360,6 +368,8 @@ export class PieceTreeTextBuffer implements ITextBuffer {
}
}
this._onDidChangeContent.fire();
return new ApplyEditsResult(
reverseOperations,
contentChanges,
+1 -1
View File
@@ -608,7 +608,7 @@ export interface CompletionItemProvider {
*
* The editor will only resolve a completion item once.
*/
resolveCompletionItem?(model: model.ITextModel, position: Position, item: CompletionItem, token: CancellationToken): ProviderResult<CompletionItem>;
resolveCompletionItem?(item: CompletionItem, token: CancellationToken): ProviderResult<CompletionItem>;
}
export interface CodeAction {
@@ -18,6 +18,7 @@ import { Schemas } from 'vs/base/common/network';
import { Emitter, Event } from 'vs/base/common/event';
import { withUndefinedAsNull } from 'vs/base/common/types';
import { minimapWarning, minimapError } from 'vs/platform/theme/common/colorRegistry';
import { Delayer } from 'vs/base/common/async';
function MODEL_ID(resource: URI): string {
return resource.toString();
@@ -41,13 +42,14 @@ class MarkerDecorations extends Disposable {
return super._register(t);
}
public update(markers: IMarker[], newDecorations: IModelDeltaDecoration[]): void {
public update(markers: IMarker[], newDecorations: IModelDeltaDecoration[]): boolean {
const oldIds = keys(this._markersData);
this._markersData.clear();
const ids = this.model.deltaDecorations(oldIds, newDecorations);
for (let index = 0; index < ids.length; index++) {
this._markersData.set(ids[index], markers[index]);
}
return oldIds.length !== 0 || ids.length !== 0;
}
getMarker(decoration: IModelDecoration): IMarker | undefined {
@@ -114,7 +116,8 @@ export class MarkerDecorationsService extends Disposable implements IMarkerDecor
private _onModelAdded(model: ITextModel): void {
const markerDecorations = new MarkerDecorations(model);
this._markerDecorations.set(MODEL_ID(model.uri), markerDecorations);
markerDecorations.register(model.onDidChangeContent(() => this._updateDecorations(markerDecorations)));
const delayer = markerDecorations.register(new Delayer(100));
markerDecorations.register(model.onDidChangeContent(() => delayer.trigger(() => this._updateDecorations(markerDecorations))));
this._updateDecorations(markerDecorations);
}
@@ -144,8 +147,9 @@ export class MarkerDecorationsService extends Disposable implements IMarkerDecor
options: this._createDecorationOption(marker)
};
});
markerDecorations.update(markers, newModelDecorations);
this._onDidChangeMarker.fire(markerDecorations.model);
if (markerDecorations.update(markers, newModelDecorations)) {
this._onDidChangeMarker.fire(markerDecorations.model);
}
}
private _createDecorationRange(model: ITextModel, rawMarker: IMarker): Range {
@@ -29,50 +29,65 @@ export class SemanticTokensProviderStyling {
let metadata: number;
if (entry) {
metadata = entry.metadata;
} else {
const tokenType = this._legend.tokenTypes[tokenTypeIndex];
const tokenModifiers: string[] = [];
let modifierSet = tokenModifierSet;
for (let modifierIndex = 0; modifierSet > 0 && modifierIndex < this._legend.tokenModifiers.length; modifierIndex++) {
if (modifierSet & 1) {
tokenModifiers.push(this._legend.tokenModifiers[modifierIndex]);
}
modifierSet = modifierSet >> 1;
if (this._logService.getLevel() === LogLevel.Trace) {
this._logService.trace(`SemanticTokensProviderStyling [CACHED] ${tokenTypeIndex} / ${tokenModifierSet}: foreground ${TokenMetadata.getForeground(metadata)}, fontStyle ${TokenMetadata.getFontStyle(metadata).toString(2)}`);
}
} else {
let tokenType = this._legend.tokenTypes[tokenTypeIndex];
const tokenModifiers: string[] = [];
if (tokenType) {
let modifierSet = tokenModifierSet;
for (let modifierIndex = 0; modifierSet > 0 && modifierIndex < this._legend.tokenModifiers.length; modifierIndex++) {
if (modifierSet & 1) {
tokenModifiers.push(this._legend.tokenModifiers[modifierIndex]);
}
modifierSet = modifierSet >> 1;
}
if (modifierSet > 0 && this._logService.getLevel() === LogLevel.Trace) {
this._logService.trace(`SemanticTokensProviderStyling: unknown token modifier index: ${tokenModifierSet.toString(2)} for legend: ${JSON.stringify(this._legend.tokenModifiers)}`);
tokenModifiers.push('not-in-legend');
}
const tokenStyle = this._themeService.getColorTheme().getTokenStyleMetadata(tokenType, tokenModifiers, languageId.language);
if (typeof tokenStyle === 'undefined') {
metadata = SemanticTokensProviderStylingConstants.NO_STYLING;
} else {
metadata = 0;
if (typeof tokenStyle.italic !== 'undefined') {
const italicBit = (tokenStyle.italic ? FontStyle.Italic : 0) << MetadataConsts.FONT_STYLE_OFFSET;
metadata |= italicBit | MetadataConsts.SEMANTIC_USE_ITALIC;
}
if (typeof tokenStyle.bold !== 'undefined') {
const boldBit = (tokenStyle.bold ? FontStyle.Bold : 0) << MetadataConsts.FONT_STYLE_OFFSET;
metadata |= boldBit | MetadataConsts.SEMANTIC_USE_BOLD;
}
if (typeof tokenStyle.underline !== 'undefined') {
const underlineBit = (tokenStyle.underline ? FontStyle.Underline : 0) << MetadataConsts.FONT_STYLE_OFFSET;
metadata |= underlineBit | MetadataConsts.SEMANTIC_USE_UNDERLINE;
}
if (tokenStyle.foreground) {
const foregroundBits = (tokenStyle.foreground) << MetadataConsts.FOREGROUND_OFFSET;
metadata |= foregroundBits | MetadataConsts.SEMANTIC_USE_FOREGROUND;
}
if (metadata === 0) {
// Nothing!
const tokenStyle = this._themeService.getColorTheme().getTokenStyleMetadata(tokenType, tokenModifiers, languageId.language);
if (typeof tokenStyle === 'undefined') {
metadata = SemanticTokensProviderStylingConstants.NO_STYLING;
} else {
metadata = 0;
if (typeof tokenStyle.italic !== 'undefined') {
const italicBit = (tokenStyle.italic ? FontStyle.Italic : 0) << MetadataConsts.FONT_STYLE_OFFSET;
metadata |= italicBit | MetadataConsts.SEMANTIC_USE_ITALIC;
}
if (typeof tokenStyle.bold !== 'undefined') {
const boldBit = (tokenStyle.bold ? FontStyle.Bold : 0) << MetadataConsts.FONT_STYLE_OFFSET;
metadata |= boldBit | MetadataConsts.SEMANTIC_USE_BOLD;
}
if (typeof tokenStyle.underline !== 'undefined') {
const underlineBit = (tokenStyle.underline ? FontStyle.Underline : 0) << MetadataConsts.FONT_STYLE_OFFSET;
metadata |= underlineBit | MetadataConsts.SEMANTIC_USE_UNDERLINE;
}
if (tokenStyle.foreground) {
const foregroundBits = (tokenStyle.foreground) << MetadataConsts.FOREGROUND_OFFSET;
metadata |= foregroundBits | MetadataConsts.SEMANTIC_USE_FOREGROUND;
}
if (metadata === 0) {
// Nothing!
metadata = SemanticTokensProviderStylingConstants.NO_STYLING;
}
}
} else {
if (this._logService.getLevel() === LogLevel.Trace) {
this._logService.trace(`SemanticTokensProviderStyling: unknown token type index: ${tokenTypeIndex} for legend: ${JSON.stringify(this._legend.tokenTypes)}`);
}
metadata = SemanticTokensProviderStylingConstants.NO_STYLING;
tokenType = 'not-in-legend';
}
this._hashTable.add(tokenTypeIndex, tokenModifierSet, languageId.id, metadata);
if (this._logService.getLevel() === LogLevel.Trace) {
this._logService.trace(`SemanticTokensProviderStyling ${tokenTypeIndex} (${tokenType}) / ${tokenModifierSet} (${tokenModifiers.join(' ')}): foreground ${TokenMetadata.getForeground(metadata)}, fontStyle ${TokenMetadata.getFontStyle(metadata).toString(2)}`);
}
}
if (this._logService.getLevel() === LogLevel.Trace) {
const type = this._legend.tokenTypes[tokenTypeIndex];
const modifiers = tokenModifierSet ? ' ' + this._legend.tokenModifiers.filter((_, i) => tokenModifierSet & (1 << i)).join(' ') : '';
this._logService.trace(`tokenStyleMetadata ${entry ? '[CACHED] ' : ''}${type}${modifiers}: foreground ${TokenMetadata.getForeground(metadata)}, fontStyle ${TokenMetadata.getFontStyle(metadata).toString(2)}`);
}
return metadata;
}
}
@@ -4,7 +4,6 @@
*--------------------------------------------------------------------------------------------*/
import 'vs/css!./codelensWidget';
import * as dom from 'vs/base/browser/dom';
import { renderCodicons } from 'vs/base/common/codicons';
import { escape } from 'vs/base/common/strings';
import { IViewZone, IContentWidget, IActiveCodeEditor, IContentWidgetPosition, ContentWidgetPositionPreference, IViewZoneChangeAccessor } from 'vs/editor/browser/editorBrowser';
@@ -113,7 +112,7 @@ class CodeLensContentWidget implements IContentWidget {
}
this._domNode.innerHTML = innerHtml;
if (this._isEmpty && animate) {
dom.addClass(this._domNode, 'fadein');
this._domNode.classList.add('fadein');
}
this._isEmpty = false;
}
@@ -102,7 +102,7 @@ export class OutlineGroupRenderer implements ITreeRenderer<OutlineGroup, FuzzySc
renderTemplate(container: HTMLElement): OutlineGroupTemplate {
const labelContainer = dom.$('.outline-element-label');
dom.addClass(container, 'outline-element');
container.classList.add('outline-element');
dom.append(container, labelContainer);
return new OutlineGroupTemplate(labelContainer, new HighlightedLabel(labelContainer, true));
}
@@ -129,7 +129,7 @@ export class OutlineElementRenderer implements ITreeRenderer<OutlineElement, Fuz
) { }
renderTemplate(container: HTMLElement): OutlineElementTemplate {
dom.addClass(container, 'outline-element');
container.classList.add('outline-element');
const iconLabel = new IconLabel(container, { supportHighlights: true });
const iconClass = dom.$('.outline-element-icon');
const decoration = dom.$('.outline-element-decoration');
@@ -184,14 +184,14 @@ export class OutlineElementRenderer implements ITreeRenderer<OutlineElement, Fuz
} else if (count > 0) {
dom.show(template.decoration);
dom.removeClass(template.decoration, 'bubble');
template.decoration.classList.remove('bubble');
template.decoration.innerText = count < 10 ? count.toString() : '+9';
template.decoration.title = count === 1 ? localize('1.problem', "1 problem in this element") : localize('N.problem', "{0} problems in this element", count);
template.decoration.style.setProperty('--outline-element-color', cssColor);
} else {
dom.show(template.decoration);
dom.addClass(template.decoration, 'bubble');
template.decoration.classList.add('bubble');
template.decoration.innerText = '\uea71';
template.decoration.title = localize('deep.problem', "Contains elements with problems");
template.decoration.style.setProperty('--outline-element-color', cssColor);
@@ -213,7 +213,7 @@ class FormatDocumentAction extends EditorAction {
id: 'editor.action.formatDocument',
label: nls.localize('formatDocument.label', "Format Document"),
alias: 'Format Document',
precondition: ContextKeyExpr.and(EditorContextKeys.writable, EditorContextKeys.hasDocumentFormattingProvider),
precondition: ContextKeyExpr.and(EditorContextKeys.notInCompositeEditor, EditorContextKeys.writable, EditorContextKeys.hasDocumentFormattingProvider),
kbOpts: {
kbExpr: ContextKeyExpr.and(EditorContextKeys.editorTextFocus, EditorContextKeys.hasDocumentFormattingProvider),
primary: KeyMod.Shift | KeyMod.Alt | KeyCode.KEY_F,
+28 -22
View File
@@ -15,7 +15,6 @@ import { Range } from 'vs/editor/common/core/range';
import { IEditorContribution } from 'vs/editor/common/editorCommon';
import { registerEditorAction, registerEditorContribution, ServicesAccessor, IActionOptions, EditorAction, EditorCommand, registerEditorCommand } from 'vs/editor/browser/editorExtensions';
import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
import { IThemeService } from 'vs/platform/theme/common/themeService';
import { EditorContextKeys } from 'vs/editor/common/editorContextKeys';
import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry';
import { MarkerNavigationWidget } from './gotoErrorWidget';
@@ -24,12 +23,10 @@ import { binarySearch, find } from 'vs/base/common/arrays';
import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService';
import { onUnexpectedError } from 'vs/base/common/errors';
import { MenuRegistry, MenuId } from 'vs/platform/actions/common/actions';
import { Action } from 'vs/base/common/actions';
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
import { isEqual } from 'vs/base/common/resources';
import { IOpenerService } from 'vs/platform/opener/common/opener';
import { TextEditorSelectionRevealType } from 'vs/platform/editor/common/editor';
import { Codicon, registerIcon } from 'vs/base/common/codicons';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
class MarkerModel {
@@ -192,9 +189,6 @@ class MarkerModel {
}
}
const markerNavigationNextIcon = registerIcon('marker-navigation-next', Codicon.chevronDown);
const markerNavigationPreviousIcon = registerIcon('marker-navigation-previous', Codicon.chevronUp);
export class MarkerController implements IEditorContribution {
public static readonly ID = 'editor.contrib.markerController';
@@ -213,10 +207,8 @@ export class MarkerController implements IEditorContribution {
editor: ICodeEditor,
@IMarkerService private readonly _markerService: IMarkerService,
@IContextKeyService private readonly _contextKeyService: IContextKeyService,
@IThemeService private readonly _themeService: IThemeService,
@ICodeEditorService private readonly _editorService: ICodeEditorService,
@IKeybindingService private readonly _keybindingService: IKeybindingService,
@IOpenerService private readonly _openerService: IOpenerService
@IInstantiationService private readonly _instantiationService: IInstantiationService,
) {
this._editor = editor;
this._widgetVisible = CONTEXT_MARKERS_NAVIGATION_VISIBLE.bindTo(this._contextKeyService);
@@ -244,21 +236,13 @@ export class MarkerController implements IEditorContribution {
this._model = new MarkerModel(this._editor, markers);
this._markerService.onMarkerChanged(this._onMarkerChanged, this, this._disposeOnClose);
const prevMarkerKeybinding = this._keybindingService.lookupKeybinding(PrevMarkerAction.ID);
const nextMarkerKeybinding = this._keybindingService.lookupKeybinding(NextMarkerAction.ID);
const actions = [
new Action(NextMarkerAction.ID, NextMarkerAction.LABEL + (nextMarkerKeybinding ? ` (${nextMarkerKeybinding.getLabel()})` : ''), 'show-next-problem ' + markerNavigationNextIcon.classNames, this._model.canNavigate(), async () => { if (this._model) { this._model.move(true, true); } }),
new Action(PrevMarkerAction.ID, PrevMarkerAction.LABEL + (prevMarkerKeybinding ? ` (${prevMarkerKeybinding.getLabel()})` : ''), 'show-previous-problem ' + markerNavigationPreviousIcon.classNames, this._model.canNavigate(), async () => { if (this._model) { this._model.move(false, true); } })
];
this._widget = new MarkerNavigationWidget(this._editor, actions, this._themeService, this._openerService);
this._widget = this._instantiationService.createInstance(MarkerNavigationWidget, this._editor);
this._widgetVisible.set(true);
this._widget.onDidClose(() => this.closeMarkersNavigation(), this, this._disposeOnClose);
this._disposeOnClose.add(this._model);
this._disposeOnClose.add(this._widget);
for (const action of actions) {
this._disposeOnClose.add(action);
}
this._disposeOnClose.add(this._widget.onDidSelectRelatedInformation(related => {
this._editorService.openCodeEditor({
resource: related.resource,
@@ -431,7 +415,18 @@ export class NextMarkerAction extends MarkerNavigationAction {
label: NextMarkerAction.LABEL,
alias: 'Go to Next Problem (Error, Warning, Info)',
precondition: undefined,
kbOpts: { kbExpr: EditorContextKeys.focus, primary: KeyMod.Alt | KeyCode.F8, weight: KeybindingWeight.EditorContrib }
kbOpts: {
kbExpr: EditorContextKeys.focus,
primary: KeyMod.Alt | KeyCode.F8,
weight: KeybindingWeight.EditorContrib
},
menuOpts: {
menuId: MarkerNavigationWidget.TitleMenu,
title: NextMarkerAction.LABEL,
icon: registerIcon('marker-navigation-next', Codicon.chevronDown),
group: 'navigation',
order: 1
}
});
}
}
@@ -445,7 +440,18 @@ class PrevMarkerAction extends MarkerNavigationAction {
label: PrevMarkerAction.LABEL,
alias: 'Go to Previous Problem (Error, Warning, Info)',
precondition: undefined,
kbOpts: { kbExpr: EditorContextKeys.focus, primary: KeyMod.Shift | KeyMod.Alt | KeyCode.F8, weight: KeybindingWeight.EditorContrib }
kbOpts: {
kbExpr: EditorContextKeys.focus,
primary: KeyMod.Shift | KeyMod.Alt | KeyCode.F8,
weight: KeybindingWeight.EditorContrib
},
menuOpts: {
menuId: MarkerNavigationWidget.TitleMenu,
title: NextMarkerAction.LABEL,
icon: registerIcon('marker-navigation-previous', Codicon.chevronUp),
group: 'navigation',
order: 2
}
});
}
}
@@ -27,6 +27,10 @@ import { IActionBarOptions, ActionsOrientation } from 'vs/base/browser/ui/action
import { SeverityIcon } from 'vs/platform/severityIcon/common/severityIcon';
import { EditorOption } from 'vs/editor/common/config/editorOptions';
import { IOpenerService } from 'vs/platform/opener/common/opener';
import { MenuId, IMenuService, MenuItemAction } from 'vs/platform/actions/common/actions';
import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { createAndFillInActionBarActions, MenuEntryActionViewItem } from 'vs/platform/actions/browser/menuEntryActionViewItem';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
class MessageWidget {
@@ -224,6 +228,8 @@ class MessageWidget {
export class MarkerNavigationWidget extends PeekViewWidget {
static readonly TitleMenu = new MenuId('gotoErrorTitleMenu');
private _parentContainer!: HTMLElement;
private _container!: HTMLElement;
private _icon!: HTMLElement;
@@ -238,9 +244,11 @@ export class MarkerNavigationWidget extends PeekViewWidget {
constructor(
editor: ICodeEditor,
private readonly actions: ReadonlyArray<IAction>,
private readonly _themeService: IThemeService,
private readonly _openerService: IOpenerService
@IThemeService private readonly _themeService: IThemeService,
@IOpenerService private readonly _openerService: IOpenerService,
@IMenuService private readonly _menuService: IMenuService,
@IContextKeyService private readonly _contextKeyService: IContextKeyService,
@IInstantiationService private readonly _instantiationService: IInstantiationService,
) {
super(editor, { showArrow: true, showFrame: true, isAccessible: true });
this._severity = MarkerSeverity.Warning;
@@ -288,7 +296,11 @@ export class MarkerNavigationWidget extends PeekViewWidget {
protected _fillHead(container: HTMLElement): void {
super._fillHead(container);
this._actionbarWidget!.push(this.actions, { label: false, icon: true, index: 0 });
const actions: IAction[] = [];
const menu = this._menuService.createMenu(MarkerNavigationWidget.TitleMenu, this._contextKeyService);
createAndFillInActionBarActions(menu, undefined, actions);
this._actionbarWidget!.push(actions, { label: false, icon: true, index: 0 });
menu.dispose();
}
protected _fillTitleIcon(container: HTMLElement): void {
@@ -297,7 +309,8 @@ export class MarkerNavigationWidget extends PeekViewWidget {
protected _getActionBarOptions(): IActionBarOptions {
return {
orientation: ActionsOrientation.HORIZONTAL
orientation: ActionsOrientation.HORIZONTAL,
actionViewItemProvider: action => action instanceof MenuItemAction ? this._instantiationService.createInstance(MenuEntryActionViewItem, action) : undefined
};
}
@@ -240,7 +240,7 @@ registerEditorAction(class GoToDefinitionAction extends DefinitionAction {
alias: 'Go to Definition',
precondition: ContextKeyExpr.and(
EditorContextKeys.hasDefinitionProvider,
EditorContextKeys.isInEmbeddedEditor.toNegated()),
EditorContextKeys.isInWalkThroughSnippet.toNegated()),
kbOpts: {
kbExpr: EditorContextKeys.editorTextFocus,
primary: goToDefinitionKb,
@@ -276,7 +276,7 @@ registerEditorAction(class OpenDefinitionToSideAction extends DefinitionAction {
alias: 'Open Definition to the Side',
precondition: ContextKeyExpr.and(
EditorContextKeys.hasDefinitionProvider,
EditorContextKeys.isInEmbeddedEditor.toNegated()),
EditorContextKeys.isInWalkThroughSnippet.toNegated()),
kbOpts: {
kbExpr: EditorContextKeys.editorTextFocus,
primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, goToDefinitionKb),
@@ -303,7 +303,7 @@ registerEditorAction(class PeekDefinitionAction extends DefinitionAction {
precondition: ContextKeyExpr.and(
EditorContextKeys.hasDefinitionProvider,
PeekContext.notInPeekEditor,
EditorContextKeys.isInEmbeddedEditor.toNegated()
EditorContextKeys.isInWalkThroughSnippet.toNegated()
),
kbOpts: {
kbExpr: EditorContextKeys.editorTextFocus,
@@ -361,7 +361,7 @@ registerEditorAction(class GoToDeclarationAction extends DeclarationAction {
alias: 'Go to Declaration',
precondition: ContextKeyExpr.and(
EditorContextKeys.hasDeclarationProvider,
EditorContextKeys.isInEmbeddedEditor.toNegated()
EditorContextKeys.isInWalkThroughSnippet.toNegated()
),
contextMenuOpts: {
group: 'navigation',
@@ -396,7 +396,7 @@ registerEditorAction(class PeekDeclarationAction extends DeclarationAction {
precondition: ContextKeyExpr.and(
EditorContextKeys.hasDeclarationProvider,
PeekContext.notInPeekEditor,
EditorContextKeys.isInEmbeddedEditor.toNegated()
EditorContextKeys.isInWalkThroughSnippet.toNegated()
),
contextMenuOpts: {
menuId: MenuId.EditorContextPeek,
@@ -447,7 +447,7 @@ registerEditorAction(class GoToTypeDefinitionAction extends TypeDefinitionAction
alias: 'Go to Type Definition',
precondition: ContextKeyExpr.and(
EditorContextKeys.hasTypeDefinitionProvider,
EditorContextKeys.isInEmbeddedEditor.toNegated()),
EditorContextKeys.isInWalkThroughSnippet.toNegated()),
kbOpts: {
kbExpr: EditorContextKeys.editorTextFocus,
primary: 0,
@@ -483,7 +483,7 @@ registerEditorAction(class PeekTypeDefinitionAction extends TypeDefinitionAction
precondition: ContextKeyExpr.and(
EditorContextKeys.hasTypeDefinitionProvider,
PeekContext.notInPeekEditor,
EditorContextKeys.isInEmbeddedEditor.toNegated()
EditorContextKeys.isInWalkThroughSnippet.toNegated()
),
contextMenuOpts: {
menuId: MenuId.EditorContextPeek,
@@ -534,7 +534,7 @@ registerEditorAction(class GoToImplementationAction extends ImplementationAction
alias: 'Go to Implementations',
precondition: ContextKeyExpr.and(
EditorContextKeys.hasImplementationProvider,
EditorContextKeys.isInEmbeddedEditor.toNegated()),
EditorContextKeys.isInWalkThroughSnippet.toNegated()),
kbOpts: {
kbExpr: EditorContextKeys.editorTextFocus,
primary: KeyMod.CtrlCmd | KeyCode.F12,
@@ -570,7 +570,7 @@ registerEditorAction(class PeekImplementationAction extends ImplementationAction
precondition: ContextKeyExpr.and(
EditorContextKeys.hasImplementationProvider,
PeekContext.notInPeekEditor,
EditorContextKeys.isInEmbeddedEditor.toNegated()
EditorContextKeys.isInWalkThroughSnippet.toNegated()
),
kbOpts: {
kbExpr: EditorContextKeys.editorTextFocus,
@@ -621,7 +621,7 @@ registerEditorAction(class GoToReferencesAction extends ReferencesAction {
precondition: ContextKeyExpr.and(
EditorContextKeys.hasReferenceProvider,
PeekContext.notInPeekEditor,
EditorContextKeys.isInEmbeddedEditor.toNegated()
EditorContextKeys.isInWalkThroughSnippet.toNegated()
),
kbOpts: {
kbExpr: EditorContextKeys.editorTextFocus,
@@ -660,7 +660,7 @@ registerEditorAction(class PeekReferencesAction extends ReferencesAction {
precondition: ContextKeyExpr.and(
EditorContextKeys.hasReferenceProvider,
PeekContext.notInPeekEditor,
EditorContextKeys.isInEmbeddedEditor.toNegated()
EditorContextKeys.isInWalkThroughSnippet.toNegated()
),
contextMenuOpts: {
menuId: MenuId.EditorContextPeek,
@@ -693,7 +693,7 @@ class GenericGoToLocationAction extends SymbolNavigationAction {
alias: 'Go To Any Symbol',
precondition: ContextKeyExpr.and(
PeekContext.notInPeekEditor,
EditorContextKeys.isInEmbeddedEditor.toNegated()
EditorContextKeys.isInWalkThroughSnippet.toNegated()
),
});
}
@@ -119,7 +119,7 @@ class FileReferencesTemplate extends Disposable {
) {
super();
const parent = document.createElement('div');
dom.addClass(parent, 'reference-file');
parent.classList.add('reference-file');
this.file = this._register(new IconLabel(parent, { supportHighlights: true }));
this.badge = new CountBadge(dom.append(parent, dom.$('.count')));
@@ -184,10 +184,10 @@ class OneReferenceTemplate {
// we have score, then render the score
const { value, highlight } = preview;
if (score && !FuzzyScore.isDefault(score)) {
dom.toggleClass(this.label.element, 'referenceMatch', false);
this.label.element.classList.toggle('referenceMatch', false);
this.label.set(value, createMatches(score));
} else {
dom.toggleClass(this.label.element, 'referenceMatch', true);
this.label.element.classList.toggle('referenceMatch', true);
this.label.set(value, [highlight]);
}
}
@@ -465,7 +465,7 @@ export class ReferenceWidget extends peekView.PeekViewWidget {
}));
// make sure things are rendered
dom.addClass(this.container!, 'results-loaded');
this.container!.classList.add('results-loaded');
dom.show(this._treeContainer);
dom.show(this._previewContainer);
this._splitView.layout(this._dim.width);
+2 -1
View File
@@ -30,7 +30,8 @@
}
.monaco-editor-hover .markdown-hover > .hover-contents:not(.code-hover-contents) hr {
min-width: 100%;
/* This is a strange rule but it avoids https://github.com/microsoft/vscode/issues/96795, just 100vw on its own caused the actual hover width to increase */
min-width: calc(100% + 100vw);
}
.monaco-editor-hover p,
@@ -15,7 +15,6 @@ import { inputBackground, inputBorder, inputForeground, widgetShadow, editorWidg
import { IColorTheme, IThemeService } from 'vs/platform/theme/common/themeService';
import { EditorOption } from 'vs/editor/common/config/editorOptions';
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
import { toggleClass } from 'vs/base/browser/dom';
import { CancellationToken } from 'vs/base/common/cancellation';
export const CONTEXT_RENAME_INPUT_VISIBLE = new RawContextKey<boolean>('renameInputVisible', false);
@@ -152,7 +151,7 @@ export class RenameInputField implements IContentWidget {
getInput(where: IRange, value: string, selectionStart: number, selectionEnd: number, supportPreview: boolean, token: CancellationToken): Promise<RenameInputFieldResult | boolean> {
toggleClass(this._domNode!, 'preview', supportPreview);
this._domNode!.classList.toggle('preview', supportPreview);
this._position = new Position(where.startLineNumber, where.startColumn);
this._input!.value = value;
@@ -5,7 +5,6 @@
import { KeyCode, KeyMod } from 'vs/base/common/keyCodes';
import { dispose, DisposableStore } from 'vs/base/common/lifecycle';
import { repeat } from 'vs/base/common/strings';
import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
import { EditorCommand, registerEditorCommand, registerEditorContribution } from 'vs/editor/browser/editorExtensions';
import { Range } from 'vs/editor/common/core/range';
@@ -191,7 +190,7 @@ export class SnippetController2 implements IEditorContribution {
insertText: option.value,
// insertText: `\${1|${after.concat(before).join(',')}|}$0`,
// snippetType: 'textmate',
sortText: repeat('a', i + 1),
sortText: 'a'.repeat(i + 1),
range: Range.fromPositions(this._editor.getPosition()!, this._editor.getPosition()!.delta(0, first.value.length))
};
}));
@@ -101,7 +101,7 @@ export class CompletionModel {
}
adopt(except: Set<CompletionItemProvider>): CompletionItem[] {
let res = new Array<CompletionItem>();
let res: CompletionItem[] = [];
for (let i = 0; i < this._items.length;) {
if (!except.has(this._items[i].provider)) {
res.push(this._items[i]);
@@ -151,6 +151,10 @@ export class CompletionModel {
const item = source[i];
if (item.isInvalid) {
continue; // SKIP invalid items
}
// collect those supports that signaled having
// an incomplete result
if (item.container.incomplete) {
+110 -103
View File
@@ -3,7 +3,6 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { first } from 'vs/base/common/async';
import { onUnexpectedExternalError, canceled, isPromiseCanceledError } from 'vs/base/common/errors';
import { IEditorContribution } from 'vs/editor/common/editorCommon';
import { ITextModel } from 'vs/editor/common/model';
@@ -34,12 +33,6 @@ export class CompletionItem {
_brand!: 'ISuggestionItem';
private static readonly _defaultResolve = () => Promise.resolve();
readonly resolve: (token: CancellationToken) => Promise<void>;
isResolved: boolean = false;
//
readonly editStart: IPosition;
readonly editInsertEnd: IPosition;
@@ -53,6 +46,9 @@ export class CompletionItem {
readonly sortTextLow?: string;
readonly filterTextLow?: string;
// validation
readonly isInvalid: boolean = false;
// sorting, filtering
score: FuzzyScore = FuzzyScore.Default;
distance: number = 0;
@@ -73,6 +69,9 @@ export class CompletionItem {
// ensure lower-variants (perf)
this.labelLow = this.textLabel.toLowerCase();
// validate label
this.isInvalid = !this.textLabel;
this.sortTextLow = completion.sortText && completion.sortText.toLowerCase();
this.filterTextLow = completion.filterText && completion.filterText.toLowerCase();
@@ -81,43 +80,54 @@ export class CompletionItem {
this.editStart = new Position(completion.range.startLineNumber, completion.range.startColumn);
this.editInsertEnd = new Position(completion.range.endLineNumber, completion.range.endColumn);
this.editReplaceEnd = new Position(completion.range.endLineNumber, completion.range.endColumn);
// validate range
this.isInvalid = this.isInvalid
|| Range.spansMultipleLines(completion.range) || completion.range.startLineNumber !== position.lineNumber;
} else {
this.editStart = new Position(completion.range.insert.startLineNumber, completion.range.insert.startColumn);
this.editInsertEnd = new Position(completion.range.insert.endLineNumber, completion.range.insert.endColumn);
this.editReplaceEnd = new Position(completion.range.replace.endLineNumber, completion.range.replace.endColumn);
// validate ranges
this.isInvalid = this.isInvalid
|| Range.spansMultipleLines(completion.range.insert) || Range.spansMultipleLines(completion.range.replace)
|| completion.range.insert.startLineNumber !== position.lineNumber || completion.range.replace.startLineNumber !== position.lineNumber
|| Range.compareRangesUsingStarts(completion.range.insert, completion.range.replace) !== 0;
}
// create the suggestion resolver
const { resolveCompletionItem } = provider;
if (typeof resolveCompletionItem !== 'function') {
this.resolve = CompletionItem._defaultResolve;
this.isResolved = true;
} else {
let cached: Promise<void> | undefined;
this.resolve = (token) => {
if (!cached) {
cached = Promise.resolve(resolveCompletionItem.call(provider, model, Position.lift(position), completion, token)).then(value => {
Object.assign(completion, value);
this.isResolved = true;
}, err => {
if (isPromiseCanceledError(err)) {
// the IPC queue will reject the request with the
// cancellation error -> reset cached
cached = undefined;
}
});
token.onCancellationRequested(() => {
if (!this.isResolved) {
// cancellation after the request has been
// dispatched -> reset cache
cached = undefined;
}
});
}
return cached;
};
if (typeof provider.resolveCompletionItem !== 'function') {
this._resolveCache = Promise.resolve();
}
}
// resolving
get isResolved() {
return Boolean(this._resolveCache);
}
private _resolveCache?: Promise<void>;
async resolve(token: CancellationToken) {
if (!this._resolveCache) {
const sub = token.onCancellationRequested(() => {
this._resolveCache = undefined;
});
this._resolveCache = Promise.resolve(this.provider.resolveCompletionItem!(this.completion, token)).then(value => {
Object.assign(this.completion, value);
sub.dispose();
}, err => {
if (isPromiseCanceledError(err)) {
// the IPC queue will reject the request with the
// cancellation error -> reset cached
this._resolveCache = undefined;
}
});
}
return this._resolveCache;
}
}
export const enum SnippetSortOrder {
@@ -147,7 +157,7 @@ export function setSnippetSuggestSupport(support: modes.CompletionItemProvider):
return old;
}
export function provideSuggestionItems(
export async function provideSuggestionItems(
model: ITextModel,
position: Position,
options: CompletionOptions = CompletionOptions.default,
@@ -155,89 +165,86 @@ export function provideSuggestionItems(
token: CancellationToken = CancellationToken.None
): Promise<CompletionItem[]> {
const word = model.getWordAtPosition(position);
const defaultReplaceRange = word ? new Range(position.lineNumber, word.startColumn, position.lineNumber, word.endColumn) : Range.fromPositions(position);
const defaultInsertRange = defaultReplaceRange.setEndPosition(position.lineNumber, position.column);
// const wordUntil = model.getWordUntilPosition(position);
// const defaultRange = new Range(position.lineNumber, wordUntil.startColumn, position.lineNumber, wordUntil.endColumn);
// const t1 = Date.now();
position = position.clone();
// get provider groups, always add snippet suggestion provider
const supports = modes.CompletionProviderRegistry.orderedGroups(model);
const word = model.getWordAtPosition(position);
const defaultReplaceRange = word ? new Range(position.lineNumber, word.startColumn, position.lineNumber, word.endColumn) : Range.fromPositions(position);
const defaultRange = { replace: defaultReplaceRange, insert: defaultReplaceRange.setEndPosition(position.lineNumber, position.column) };
// add snippets provider unless turned off
if (!options.kindFilter.has(modes.CompletionItemKind.Snippet) && _snippetSuggestSupport) {
supports.unshift([_snippetSuggestSupport]);
}
const allSuggestions: CompletionItem[] = [];
const result: CompletionItem[] = [];
const disposables = new DisposableStore();
let hasResult = false;
const onCompletionList = (provider: modes.CompletionItemProvider, container: modes.CompletionList | null | undefined) => {
if (!container) {
return;
}
for (let suggestion of container.suggestions || []) {
if (!options.kindFilter.has(suggestion.kind)) {
// fill in default range when missing
if (!suggestion.range) {
suggestion.range = defaultRange;
}
// fill in default sortText when missing
if (!suggestion.sortText) {
suggestion.sortText = typeof suggestion.label === 'string' ? suggestion.label : suggestion.label.name;
}
result.push(new CompletionItem(position, suggestion, container, provider, model));
}
}
if (isDisposable(container)) {
disposables.add(container);
}
};
// ask for snippets in parallel to asking "real" providers. Only do something if configured to
// do so - no snippet filter, no special-providers-only request
const snippetCompletions = new Promise<void>((resolve, reject) => {
if (!_snippetSuggestSupport || options.kindFilter.has(modes.CompletionItemKind.Snippet)) {
resolve();
}
if (options.providerFilter.size > 0 && !options.providerFilter.has(_snippetSuggestSupport)) {
resolve();
}
Promise.resolve(_snippetSuggestSupport.provideCompletionItems(model, position, context, token)).then(list => {
onCompletionList(_snippetSuggestSupport, list);
resolve();
}, reject);
});
// add suggestions from contributed providers - providers are ordered in groups of
// equal score and once a group produces a result the process stops
const factory = supports.map(supports => () => {
// get provider groups, always add snippet suggestion provider
for (let providerGroup of modes.CompletionProviderRegistry.orderedGroups(model)) {
// for each support in the group ask for suggestions
return Promise.all(supports.map(provider => {
let lenBefore = result.length;
await Promise.all(providerGroup.map(async provider => {
if (options.providerFilter.size > 0 && !options.providerFilter.has(provider)) {
return undefined;
return;
}
try {
const list = await provider.provideCompletionItems(model, position, context, token);
onCompletionList(provider, list);
} catch (err) {
onUnexpectedExternalError(err);
}
return Promise.resolve(provider.provideCompletionItems(model, position, context, token)).then(container => {
const len = allSuggestions.length;
if (container) {
for (let suggestion of container.suggestions || []) {
if (!options.kindFilter.has(suggestion.kind)) {
// fill in default range when missing
if (!suggestion.range) {
suggestion.range = { insert: defaultInsertRange, replace: defaultReplaceRange };
}
// fill in default sortText when missing
if (!suggestion.sortText) {
suggestion.sortText = typeof suggestion.label === 'string' ? suggestion.label : suggestion.label.name;
}
allSuggestions.push(new CompletionItem(position, suggestion, container, provider, model));
}
}
if (isDisposable(container)) {
disposables.add(container);
}
}
if (len !== allSuggestions.length && provider !== _snippetSuggestSupport) {
hasResult = true;
}
}, onUnexpectedExternalError);
}));
});
const result = first(factory, () => {
// stop on result or cancellation
return hasResult || token.isCancellationRequested;
}).then(() => {
if (token.isCancellationRequested) {
disposables.dispose();
return Promise.reject<any>(canceled());
if (lenBefore !== result.length || token.isCancellationRequested) {
break;
}
return allSuggestions.sort(getSuggestionComparator(options.snippetSortOrder));
});
}
// result.then(items => {
// console.log(model.getWordUntilPosition(position), items.map(item => `${item.suggestion.label}, type=${item.suggestion.type}, incomplete?${item.container.incomplete}, overwriteBefore=${item.suggestion.overwriteBefore}`));
// return items;
// }, err => {
// console.warn(model.getWordUntilPosition(position), err);
// });
await snippetCompletions;
return result;
if (token.isCancellationRequested) {
disposables.dispose();
return Promise.reject<any>(canceled());
}
// console.log(`${result.length} items AFTER ${Date.now() - t1}ms`);
return result.sort(getSuggestionComparator(options.snippetSortOrder));
}
@@ -8,6 +8,7 @@ import { isNonEmptyArray } from 'vs/base/common/arrays';
import { onUnexpectedError } from 'vs/base/common/errors';
import { KeyCode, KeyMod, SimpleKeybinding } from 'vs/base/common/keyCodes';
import { dispose, IDisposable, DisposableStore, toDisposable, MutableDisposable } from 'vs/base/common/lifecycle';
import { StableEditorScrollState } from 'vs/editor/browser/core/editorState';
import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
import { EditorAction, EditorCommand, registerEditorAction, registerEditorCommand, registerEditorContribution, ServicesAccessor } from 'vs/editor/browser/editorExtensions';
import { EditOperation } from 'vs/editor/common/core/editOperation';
@@ -273,6 +274,8 @@ export class SuggestController implements IEditorContribution {
// keep item in memory
this._memoryService.memorize(model, this.editor.getPosition(), item);
const scrollState = StableEditorScrollState.capture(this.editor);
if (Array.isArray(suggestion.additionalTextEdits)) {
this.editor.executeEdits('suggestController.additionalTextEdits', suggestion.additionalTextEdits.map(edit => EditOperation.replace(Range.lift(edit.range), edit.text)));
}
@@ -290,6 +293,8 @@ export class SuggestController implements IEditorContribution {
adjustWhitespace: !(suggestion.insertTextRules! & CompletionItemInsertTextRule.KeepWhitespace)
});
scrollState.restoreRelativeVerticalPositionOfCursor(this.editor);
if (!(flags & InsertFlags.NoAfterUndoStop)) {
this.editor.pushUndoStop();
}
+27 -29
View File
@@ -13,7 +13,7 @@ import * as strings from 'vs/base/common/strings';
import { Event, Emitter } from 'vs/base/common/event';
import { onUnexpectedError } from 'vs/base/common/errors';
import { IDisposable, dispose, toDisposable, DisposableStore, Disposable } from 'vs/base/common/lifecycle';
import { addClass, append, $, hide, removeClass, show, toggleClass, getDomNodePagePosition, hasClass, addDisposableListener, addStandardDisposableListener, addClasses } from 'vs/base/browser/dom';
import { append, $, hide, show, getDomNodePagePosition, addDisposableListener, addStandardDisposableListener, addClasses } from 'vs/base/browser/dom';
import { IListVirtualDelegate, IListEvent, IListRenderer, IListMouseEvent, IListGestureEvent } from 'vs/base/browser/ui/list/list';
import { List } from 'vs/base/browser/ui/list/listWidget';
import { DomScrollableElement } from 'vs/base/browser/ui/scrollbar/scrollableElement';
@@ -139,7 +139,7 @@ class ItemRenderer implements IListRenderer<CompletionItem, ISuggestionTemplateD
data.disposables = new DisposableStore();
data.root = container;
addClass(data.root, 'show-file-icons');
data.root.classList.add('show-file-icons');
data.icon = append(container, $('.icon'));
data.colorspan = append(data.icon, $('span.colorspan'));
@@ -245,16 +245,16 @@ class ItemRenderer implements IListRenderer<CompletionItem, ISuggestionTemplateD
data.parametersLabel.textContent = '';
data.qualifierLabel.textContent = '';
data.detailsLabel.textContent = (suggestion.detail || '').replace(/\n.*$/m, '');
addClass(data.root, 'string-label');
data.root.classList.add('string-label');
} else {
data.parametersLabel.textContent = (suggestion.label.parameters || '').replace(/\n.*$/m, '');
data.qualifierLabel.textContent = (suggestion.label.qualifier || '').replace(/\n.*$/m, '');
data.detailsLabel.textContent = (suggestion.label.type || '').replace(/\n.*$/m, '');
removeClass(data.root, 'string-label');
data.root.classList.remove('string-label');
}
if (canExpandCompletionItem(element)) {
addClass(data.right, 'can-expand-details');
data.right.classList.add('can-expand-details');
show(data.readMore);
data.readMore.onmousedown = e => {
e.stopPropagation();
@@ -266,7 +266,7 @@ class ItemRenderer implements IListRenderer<CompletionItem, ISuggestionTemplateD
this.widget.toggleDetails();
};
} else {
removeClass(data.right, 'can-expand-details');
data.right.classList.remove('can-expand-details');
hide(data.readMore);
data.readMore.onmousedown = null;
data.readMore.onclick = null;
@@ -363,15 +363,15 @@ class SuggestionDetails {
if (!explainMode && !canExpandCompletionItem(item)) {
this.type.textContent = '';
this.docs.textContent = '';
addClass(this.el, 'no-docs');
this.el.classList.add('no-docs');
return;
}
removeClass(this.el, 'no-docs');
this.el.classList.remove('no-docs');
if (typeof documentation === 'string') {
removeClass(this.docs, 'markdown-docs');
this.docs.classList.remove('markdown-docs');
this.docs.textContent = documentation;
} else {
addClass(this.docs, 'markdown-docs');
this.docs.classList.add('markdown-docs');
this.docs.innerHTML = '';
const renderedContents = this.markdownRenderer.render(documentation);
this.renderDisposeable = renderedContents;
@@ -554,7 +554,7 @@ export class SuggestWidget implements IContentWidget, IListVirtualDelegate<Compl
this.messageElement = append(this.element, $('.message'));
this.listElement = append(this.element, $('.tree'));
const applyStatusBarStyle = () => toggleClass(this.element, 'with-status-bar', this.editor.getOption(EditorOption.suggest).statusBar.visible);
const applyStatusBarStyle = () => this.element.classList.toggle('with-status-bar', this.editor.getOption(EditorOption.suggest).statusBar.visible);
applyStatusBarStyle();
this.statusBarElement = append(this.element, $('.suggest-status-bar'));
@@ -598,7 +598,7 @@ export class SuggestWidget implements IContentWidget, IListVirtualDelegate<Compl
this.details = instantiationService.createInstance(SuggestionDetails, this.element, this, this.editor, markdownRenderer, kbToggleDetails);
const applyIconStyle = () => toggleClass(this.element, 'no-icons', !this.editor.getOption(EditorOption.suggest).showIcons);
const applyIconStyle = () => this.element.classList.toggle('no-icons', !this.editor.getOption(EditorOption.suggest).showIcons);
applyIconStyle();
let renderer = instantiationService.createInstance(ItemRenderer, this, this.editor, kbToggleDetails);
@@ -797,7 +797,7 @@ export class SuggestWidget implements IContentWidget, IListVirtualDelegate<Compl
if (this.expandDocsSettingFromStorage()) {
this.showDetails(false);
} else {
removeClass(this.element, 'docs-side');
this.element.classList.remove('docs-side');
}
this.editor.setAriaOptions({ activeDescendant: getAriaId(index) });
@@ -821,7 +821,7 @@ export class SuggestWidget implements IContentWidget, IListVirtualDelegate<Compl
const stateChanged = this.state !== state;
this.state = state;
toggleClass(this.element, 'frozen', state === State.Frozen);
this.element.classList.toggle('frozen', state === State.Frozen);
switch (state) {
case State.Hidden:
@@ -837,7 +837,7 @@ export class SuggestWidget implements IContentWidget, IListVirtualDelegate<Compl
this.messageElement.textContent = SuggestWidget.LOADING_MESSAGE;
hide(this.listElement, this.details.element, this.statusBarElement);
show(this.messageElement);
removeClass(this.element, 'docs-side');
this.element.classList.remove('docs-side');
this.show();
this.focusedItem = null;
break;
@@ -845,7 +845,7 @@ export class SuggestWidget implements IContentWidget, IListVirtualDelegate<Compl
this.messageElement.textContent = SuggestWidget.NO_SUGGESTIONS_MESSAGE;
hide(this.listElement, this.details.element, this.statusBarElement);
show(this.messageElement);
removeClass(this.element, 'docs-side');
this.element.classList.remove('docs-side');
this.show();
this.focusedItem = null;
break;
@@ -1072,8 +1072,7 @@ export class SuggestWidget implements IContentWidget, IListVirtualDelegate<Compl
this.ctxSuggestWidgetDetailsVisible.set(false);
this.updateExpandDocsSetting(false);
hide(this.details.element);
removeClass(this.element, 'docs-side');
removeClass(this.element, 'docs-below');
this.element.classList.remove('docs-side', 'doc-below');
this.editor.layoutContentWidget(this);
this.telemetryService.publicLog2('suggestWidget:collapseDetails');
} else {
@@ -1132,7 +1131,7 @@ export class SuggestWidget implements IContentWidget, IListVirtualDelegate<Compl
this.ctxSuggestWidgetVisible.set(true);
this.showTimeout.cancelAndSet(() => {
addClass(this.element, 'visible');
this.element.classList.add('visible');
this.onDidShowEmitter.fire(this);
}, 100);
}
@@ -1140,7 +1139,7 @@ export class SuggestWidget implements IContentWidget, IListVirtualDelegate<Compl
private hide(): void {
this.ctxSuggestWidgetVisible.reset();
this.ctxSuggestWidgetMultipleSuggestions.reset();
removeClass(this.element, 'visible');
this.element.classList.remove('visible');
}
hideWidget(): void {
@@ -1225,15 +1224,15 @@ export class SuggestWidget implements IContentWidget, IListVirtualDelegate<Compl
if (widgetX < cursorX - this.listWidth) {
// Widget is too far to the left of cursor, swap list and docs
addClass(this.element, 'list-right');
this.element.classList.add('list-right');
} else {
removeClass(this.element, 'list-right');
this.element.classList.remove('list-right');
}
// Compare top of the cursor (cursorY - lineheight) with widgetTop to determine if
// margin-top needs to be applied on list to make it appear right above the cursor
// Cannot compare cursorY directly as it may be a few decimals off due to zoooming
if (hasClass(this.element, 'docs-side')
if (this.element.classList.contains('docs-side')
&& cursorY - lineHeight > widgetY
&& this.details.element.offsetHeight > this.listElement.offsetHeight) {
@@ -1248,18 +1247,17 @@ export class SuggestWidget implements IContentWidget, IListVirtualDelegate<Compl
*/
private expandSideOrBelow() {
if (!canExpandCompletionItem(this.focusedItem) && this.firstFocusInCurrentList) {
removeClass(this.element, 'docs-side');
removeClass(this.element, 'docs-below');
this.element.classList.remove('docs-side', 'docs-below');
return;
}
let matches = this.element.style.maxWidth!.match(/(\d+)px/);
if (!matches || Number(matches[1]) < this.maxWidgetWidth) {
addClass(this.element, 'docs-below');
removeClass(this.element, 'docs-side');
this.element.classList.add('docs-below');
this.element.classList.remove('docs-side');
} else if (canExpandCompletionItem(this.focusedItem)) {
addClass(this.element, 'docs-side');
removeClass(this.element, 'docs-below');
this.element.classList.add('docs-side');
this.element.classList.remove('docs-below');
}
}
@@ -757,7 +757,7 @@ suite('SuggestModel - TriggerAndCancelOracle', function () {
dispose() { disposeB += 1; }
};
},
resolveCompletionItem(doc, pos, item) {
resolveCompletionItem(item) {
return item;
},
}));
@@ -214,13 +214,13 @@ export abstract class ZoneWidget implements IHorizontalSashLayoutProvider {
create(): void {
dom.addClass(this.domNode, 'zone-widget');
this.domNode.classList.add('zone-widget');
if (this.options.className) {
dom.addClass(this.domNode, this.options.className);
this.domNode.classList.add(this.options.className);
}
this.container = document.createElement('div');
dom.addClass(this.container, 'zone-widget-container');
this.container.classList.add('zone-widget-container');
this.domNode.appendChild(this.container);
if (this.options.showArrow) {
this._arrow = new Arrow(this.editor);
+1 -1
View File
@@ -5590,7 +5590,7 @@ declare namespace monaco.languages {
*
* The editor will only resolve a completion item once.
*/
resolveCompletionItem?(model: editor.ITextModel, position: Position, item: CompletionItem, token: CancellationToken): ProviderResult<CompletionItem>;
resolveCompletionItem?(item: CompletionItem, token: CancellationToken): ProviderResult<CompletionItem>;
}
export interface CodeAction {
+77 -42
View File
@@ -9,11 +9,13 @@ import { IConstructorSignature2, createDecorator, BrandedService, ServicesAccess
import { IKeybindings, KeybindingsRegistry, IKeybindingRule } from 'vs/platform/keybinding/common/keybindingsRegistry';
import { ContextKeyExpr, IContextKeyService, ContextKeyExpression } from 'vs/platform/contextkey/common/contextkey';
import { ICommandService, CommandsRegistry, ICommandHandlerDescription } from 'vs/platform/commands/common/commands';
import { IDisposable, DisposableStore } from 'vs/base/common/lifecycle';
import { IDisposable, DisposableStore, toDisposable } from 'vs/base/common/lifecycle';
import { Event, Emitter } from 'vs/base/common/event';
import { URI } from 'vs/base/common/uri';
import { ThemeIcon } from 'vs/platform/theme/common/themeService';
import { UriDto } from 'vs/base/common/types';
import { Iterable } from 'vs/base/common/iterator';
import { LinkedList } from 'vs/base/common/linkedList';
export interface ILocalizedString {
value: string;
@@ -159,33 +161,51 @@ export interface IMenuService {
export type ICommandsMap = Map<string, ICommandAction>;
export interface IMenuRegistryChangeEvent {
has(id: MenuId): boolean;
}
export interface IMenuRegistry {
readonly onDidChangeMenu: Event<IMenuRegistryChangeEvent>;
addCommands(newCommands: Iterable<ICommandAction>): IDisposable;
addCommand(userCommand: ICommandAction): IDisposable;
getCommand(id: string): ICommandAction | undefined;
getCommands(): ICommandsMap;
appendMenuItems(items: Iterable<{ id: MenuId, item: IMenuItem | ISubmenuItem }>): IDisposable;
appendMenuItem(menu: MenuId, item: IMenuItem | ISubmenuItem): IDisposable;
getMenuItems(loc: MenuId): Array<IMenuItem | ISubmenuItem>;
readonly onDidChangeMenu: Event<MenuId>;
}
export const MenuRegistry: IMenuRegistry = new class implements IMenuRegistry {
private readonly _commands = new Map<string, ICommandAction>();
private readonly _menuItems = new Map<MenuId, Array<IMenuItem | ISubmenuItem>>();
private readonly _onDidChangeMenu = new Emitter<MenuId>();
private readonly _menuItems = new Map<MenuId, LinkedList<IMenuItem | ISubmenuItem>>();
private readonly _onDidChangeMenu = new Emitter<IMenuRegistryChangeEvent>();
readonly onDidChangeMenu: Event<MenuId> = this._onDidChangeMenu.event;
readonly onDidChangeMenu: Event<IMenuRegistryChangeEvent> = this._onDidChangeMenu.event;
addCommand(command: ICommandAction): IDisposable {
this._commands.set(command.id, command);
this._onDidChangeMenu.fire(MenuId.CommandPalette);
return {
dispose: () => {
if (this._commands.delete(command.id)) {
this._onDidChangeMenu.fire(MenuId.CommandPalette);
}
return this.addCommands(Iterable.single(command));
}
private readonly _commandPaletteChangeEvent: IMenuRegistryChangeEvent = {
has: id => id === MenuId.CommandPalette
};
addCommands(commands: Iterable<ICommandAction>): IDisposable {
for (const command of commands) {
this._commands.set(command.id, command);
}
this._onDidChangeMenu.fire(this._commandPaletteChangeEvent);
return toDisposable(() => {
let didChange = false;
for (const command of commands) {
didChange = this._commands.delete(command.id) || didChange;
}
};
if (didChange) {
this._onDidChangeMenu.fire(this._commandPaletteChangeEvent);
}
});
}
getCommand(id: string): ICommandAction | undefined {
@@ -199,28 +219,44 @@ export const MenuRegistry: IMenuRegistry = new class implements IMenuRegistry {
}
appendMenuItem(id: MenuId, item: IMenuItem | ISubmenuItem): IDisposable {
let array = this._menuItems.get(id);
if (!array) {
array = [item];
this._menuItems.set(id, array);
} else {
array.push(item);
}
this._onDidChangeMenu.fire(id);
return {
dispose: () => {
const idx = array!.indexOf(item);
if (idx >= 0) {
array!.splice(idx, 1);
this._onDidChangeMenu.fire(id);
}
return this.appendMenuItems(Iterable.single({ id, item }));
}
appendMenuItems(items: Iterable<{ id: MenuId, item: IMenuItem | ISubmenuItem }>): IDisposable {
const changedIds = new Set<MenuId>();
const toRemove = new LinkedList<Function>();
for (const { id, item } of items) {
let list = this._menuItems.get(id);
if (!list) {
list = new LinkedList();
this._menuItems.set(id, list);
}
};
toRemove.push(list.push(item));
changedIds.add(id);
}
this._onDidChangeMenu.fire(changedIds);
return toDisposable(() => {
if (toRemove.size > 0) {
for (let fn of toRemove) {
fn();
}
this._onDidChangeMenu.fire(changedIds);
toRemove.clear();
}
});
}
getMenuItems(id: MenuId): Array<IMenuItem | ISubmenuItem> {
const result = (this._menuItems.get(id) || []).slice(0);
let result: Array<IMenuItem | ISubmenuItem>;
if (this._menuItems.has(id)) {
result = [...this._menuItems.get(id)!];
} else {
result = [];
}
if (id === MenuId.CommandPalette) {
// CommandPalette is special because it shows
// all commands by default
@@ -232,12 +268,12 @@ export const MenuRegistry: IMenuRegistry = new class implements IMenuRegistry {
private _appendImplicitItems(result: Array<IMenuItem | ISubmenuItem>) {
const set = new Set<string>();
const temp = result.filter(item => { return isIMenuItem(item); }) as IMenuItem[];
for (const { command, alt } of temp) {
set.add(command.id);
if (alt) {
set.add(alt.id);
for (const item of result) {
if (isIMenuItem(item)) {
set.add(item.command.id);
if (item.alt) {
set.add(item.alt.id);
}
}
}
this._commands.forEach((command, id) => {
@@ -441,14 +477,13 @@ export function registerAction2(ctor: { new(): Action2 }): IDisposable {
// menu
if (Array.isArray(menu)) {
for (let item of menu) {
disposables.add(MenuRegistry.appendMenuItem(item.id, { command: { ...command }, ...item }));
}
disposables.add(MenuRegistry.appendMenuItems(menu.map(item => ({ id: item.id, item: { command, ...item } }))));
} else if (menu) {
disposables.add(MenuRegistry.appendMenuItem(menu.id, { command: { ...command }, ...menu }));
disposables.add(MenuRegistry.appendMenuItem(menu.id, { command, ...menu }));
}
if (f1) {
disposables.add(MenuRegistry.appendMenuItem(MenuId.CommandPalette, { command: command }));
disposables.add(MenuRegistry.appendMenuItem(MenuId.CommandPalette, { command }));
}
// keybinding
@@ -45,7 +45,7 @@ class Menu implements IMenu {
// rebuild this menu whenever the menu registry reports an
// event for this MenuId
this._dispoables.add(Event.debounce(
Event.filter(MenuRegistry.onDidChangeMenu, menuId => menuId === this._id),
Event.filter(MenuRegistry.onDidChangeMenu, set => set.has(this._id)),
() => { },
50
)(this._build, this));
+1 -2
View File
@@ -9,7 +9,6 @@ import { ServicesAccessor, createDecorator } from 'vs/platform/instantiation/com
import { Event, Emitter } from 'vs/base/common/event';
import { LinkedList } from 'vs/base/common/linkedList';
import { IJSONSchema } from 'vs/base/common/jsonSchema';
import { keys } from 'vs/base/common/map';
import { Iterable } from 'vs/base/common/iterator';
export const ICommandService = createDecorator<ICommandService>('commandService');
@@ -130,7 +129,7 @@ export const CommandsRegistry: ICommandRegistry = new class implements ICommandR
getCommands(): ICommandsMap {
const result = new Map<string, ICommand>();
for (const key of keys(this._commands)) {
for (const key of this._commands.keys()) {
const command = this.getCommand(key);
if (command) {
result.set(key, command);
@@ -231,7 +231,7 @@ export class ConfigurationModelParser {
}
public parseContent(content: string | null | undefined): void {
if (content) {
if (!types.isUndefinedOrNull(content)) {
const raw = this.doParseContent(content);
this.parseRaw(raw);
}
@@ -677,7 +677,7 @@ export class Configuration {
overrides: this._workspaceConfiguration.overrides,
keys: this._workspaceConfiguration.keys
},
folders: this._folderConfigurations.keys().reduce<[UriComponents, IConfigurationModel][]>((result, folder) => {
folders: [...this._folderConfigurations.keys()].reduce<[UriComponents, IConfigurationModel][]>((result, folder) => {
const { contents, overrides, keys } = this._folderConfigurations.get(folder)!;
result.push([folder, { contents, overrides, keys }]);
return result;
@@ -21,14 +21,13 @@ import { isLinux, isWindows } from 'vs/base/common/platform';
import { DisposableStore } from 'vs/base/common/lifecycle';
import { isEqual, joinPath } from 'vs/base/common/resources';
import { VSBuffer, VSBufferReadable, streamToBufferReadableStream, VSBufferReadableStream, bufferToReadable, bufferToStream, streamToBuffer } from 'vs/base/common/buffer';
import { find } from 'vs/base/common/arrays';
function getByName(root: IFileStat, name: string): IFileStat | undefined {
if (root.children === undefined) {
return undefined;
}
return find(root.children, child => child.name === name);
return root.children.find(child => child.name === name);
}
function toLineByLineReadable(content: string): VSBufferReadable {
@@ -442,7 +441,7 @@ suite('Disk File Service', function () {
assert.equal(resolved.isDirectory, true);
assert.equal(resolved.children!.length, 9);
const resolvedLink = resolved.children?.filter(child => child.name === 'bar' && child.isSymbolicLink)[0];
const resolvedLink = resolved.children?.find(child => child.name === 'bar' && child.isSymbolicLink);
assert.ok(resolvedLink);
assert.ok(!resolvedLink?.isDirectory);
+32 -40
View File
@@ -3,86 +3,78 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { isEmptyObject } from 'vs/base/common/types';
import { forEach } from 'vs/base/common/collections';
export class Node<T> {
export interface Node<T> {
data: T;
incoming: { [key: string]: Node<T> };
outgoing: { [key: string]: Node<T> };
}
readonly data: T;
readonly incoming = new Map<string, Node<T>>();
readonly outgoing = new Map<string, Node<T>>();
function newNode<T>(data: T): Node<T> {
return {
data: data,
incoming: Object.create(null),
outgoing: Object.create(null)
};
constructor(data: T) {
this.data = data;
}
}
export class Graph<T> {
private _nodes: { [key: string]: Node<T> } = Object.create(null);
private readonly _nodes = new Map<string, Node<T>>();
constructor(private _hashFn: (element: T) => string) {
constructor(private readonly _hashFn: (element: T) => string) {
// empty
}
roots(): Node<T>[] {
const ret: Node<T>[] = [];
forEach(this._nodes, entry => {
if (isEmptyObject(entry.value.outgoing)) {
ret.push(entry.value);
for (let node of this._nodes.values()) {
if (node.outgoing.size === 0) {
ret.push(node);
}
});
}
return ret;
}
insertEdge(from: T, to: T): void {
const fromNode = this.lookupOrInsertNode(from),
toNode = this.lookupOrInsertNode(to);
const fromNode = this.lookupOrInsertNode(from);
const toNode = this.lookupOrInsertNode(to);
fromNode.outgoing[this._hashFn(to)] = toNode;
toNode.incoming[this._hashFn(from)] = fromNode;
fromNode.outgoing.set(this._hashFn(to), toNode);
toNode.incoming.set(this._hashFn(from), fromNode);
}
removeNode(data: T): void {
const key = this._hashFn(data);
delete this._nodes[key];
forEach(this._nodes, (entry) => {
delete entry.value.outgoing[key];
delete entry.value.incoming[key];
});
this._nodes.delete(key);
for (let node of this._nodes.values()) {
node.outgoing.delete(key);
node.incoming.delete(key);
}
}
lookupOrInsertNode(data: T): Node<T> {
const key = this._hashFn(data);
let node = this._nodes[key];
let node = this._nodes.get(key);
if (!node) {
node = newNode(data);
this._nodes[key] = node;
node = new Node(data);
this._nodes.set(key, node);
}
return node;
}
lookup(data: T): Node<T> {
return this._nodes[this._hashFn(data)];
lookup(data: T): Node<T> | undefined {
return this._nodes.get(this._hashFn(data));
}
isEmpty(): boolean {
for (const _key in this._nodes) {
return false;
}
return true;
return this._nodes.size === 0;
}
toString(): string {
let data: string[] = [];
forEach(this._nodes, entry => {
data.push(`${entry.key}, (incoming)[${Object.keys(entry.value.incoming).join(', ')}], (outgoing)[${Object.keys(entry.value.outgoing).join(',')}]`);
});
for (let [key, value] of this._nodes) {
data.push(`${key}, (incoming)[${[...value.incoming.keys()].join(', ')}], (outgoing)[${[...value.outgoing.keys()].join(',')}]`);
}
return data.join('\n');
}
}
@@ -19,7 +19,7 @@ suite('Graph', () => {
test('inserts nodes when not there yet', function () {
assert.deepEqual(graph.lookup('ddd'), null);
assert.deepEqual(graph.lookupOrInsertNode('ddd').data, 'ddd');
assert.deepEqual(graph.lookup('ddd').data, 'ddd');
assert.deepEqual(graph.lookup('ddd')!.data, 'ddd');
});
test('can remove nodes and get length', function () {
+4 -3
View File
@@ -658,6 +658,7 @@ abstract class ResourceNavigator<T> extends Disposable {
onDidChangeFocus: Event<{ browserEvent?: UIEvent }>,
onDidChangeSelection: Event<{ browserEvent?: UIEvent }>,
onDidOpen: Event<{ browserEvent?: UIEvent }>,
readonly openOnSingleClick?: boolean
},
options?: IResourceNavigatorOptions
) {
@@ -711,7 +712,7 @@ abstract class ResourceNavigator<T> extends Disposable {
!!(<SelectionKeyboardEvent>browserEvent).preserveFocus :
!isDoubleClick;
if (this.options.openOnSingleClick || isDoubleClick || isKeyboardEvent) {
if (this.treeOrList.openOnSingleClick || isDoubleClick || isKeyboardEvent) {
const sideBySide = browserEvent instanceof MouseEvent && (browserEvent.ctrlKey || browserEvent.metaKey || browserEvent.altKey);
this.open(preserveFocus, isDoubleClick || isMiddleClick, sideBySide, browserEvent);
}
@@ -738,8 +739,8 @@ export class ListResourceNavigator<T> extends ResourceNavigator<number> {
}
export class TreeResourceNavigator<T, TFilterData> extends ResourceNavigator<T> {
constructor(tree: WorkbenchObjectTree<T, TFilterData> | WorkbenchCompressibleObjectTree<T, TFilterData> | WorkbenchDataTree<any, T, TFilterData> | WorkbenchAsyncDataTree<any, T, TFilterData> | WorkbenchCompressibleAsyncDataTree<any, T, TFilterData>, options?: IResourceNavigatorOptions) {
super(tree, { openOnSingleClick: tree.openOnSingleClick, ...(options || {}) });
constructor(tree: WorkbenchObjectTree<T, TFilterData> | WorkbenchCompressibleObjectTree<T, TFilterData> | WorkbenchDataTree<any, T, TFilterData> | WorkbenchAsyncDataTree<any, T, TFilterData> | WorkbenchCompressibleAsyncDataTree<any, T, TFilterData>, options: IResourceNavigatorOptions = {}) {
super(tree, options);
}
}
+84 -91
View File
@@ -6,40 +6,64 @@
import { isFalsyOrEmpty, isNonEmptyArray } from 'vs/base/common/arrays';
import { Schemas } from 'vs/base/common/network';
import { IDisposable } from 'vs/base/common/lifecycle';
import { isEmptyObject } from 'vs/base/common/types';
import { URI } from 'vs/base/common/uri';
import { Event, Emitter } from 'vs/base/common/event';
import { IMarkerService, IMarkerData, IResourceMarker, IMarker, MarkerStatistics, MarkerSeverity } from './markers';
import { ResourceMap } from 'vs/base/common/map';
import { Iterable } from 'vs/base/common/iterator';
interface MapMap<V> {
[key: string]: { [key: string]: V };
}
class DoubleResourceMap<V>{
namespace MapMap {
private _byResource = new ResourceMap<Map<string, V>>();
private _byOwner = new Map<string, ResourceMap<V>>();
export function get<V>(map: MapMap<V>, key1: string, key2: string): V | undefined {
if (map[key1]) {
return map[key1][key2];
set(resource: URI, owner: string, value: V) {
let ownerMap = this._byResource.get(resource);
if (!ownerMap) {
ownerMap = new Map();
this._byResource.set(resource, ownerMap);
}
return undefined;
ownerMap.set(owner, value);
let resourceMap = this._byOwner.get(owner);
if (!resourceMap) {
resourceMap = new ResourceMap();
this._byOwner.set(owner, resourceMap);
}
resourceMap.set(resource, value);
}
export function set<V>(map: MapMap<V>, key1: string, key2: string, value: V): void {
if (!map[key1]) {
map[key1] = Object.create(null);
}
map[key1][key2] = value;
get(resource: URI, owner: string): V | undefined {
let ownerMap = this._byResource.get(resource);
return ownerMap?.get(owner);
}
export function remove(map: MapMap<any>, key1: string, key2: string): boolean {
if (map[key1] && map[key1][key2]) {
delete map[key1][key2];
if (isEmptyObject(map[key1])) {
delete map[key1];
}
return true;
delete(resource: URI, owner: string): boolean {
let removedA = false;
let removedB = false;
let ownerMap = this._byResource.get(resource);
if (ownerMap) {
removedA = ownerMap.delete(owner);
}
return false;
let resourceMap = this._byOwner.get(owner);
if (resourceMap) {
removedB = resourceMap.delete(resource);
}
if (removedA !== removedB) {
throw new Error('illegal state');
}
return removedA && removedB;
}
values(key?: URI | string): Iterable<V> {
if (typeof key === 'string') {
return this._byOwner.get(key)?.values() ?? Iterable.empty();
}
if (URI.isUri(key)) {
return this._byResource.get(key)?.values() ?? Iterable.empty();
}
return Iterable.map(Iterable.concat(...this._byOwner.values()), map => map[1]);
}
}
@@ -50,9 +74,9 @@ class MarkerStats implements MarkerStatistics {
warnings: number = 0;
unknowns: number = 0;
private _data?: { [resource: string]: MarkerStatistics } = Object.create(null);
private _service: IMarkerService;
private _subscription: IDisposable;
private readonly _data = new ResourceMap<MarkerStatistics>();
private readonly _service: IMarkerService;
private readonly _subscription: IDisposable;
constructor(service: IMarkerService) {
this._service = service;
@@ -61,23 +85,17 @@ class MarkerStats implements MarkerStatistics {
dispose(): void {
this._subscription.dispose();
this._data = undefined;
}
private _update(resources: readonly URI[]): void {
if (!this._data) {
return;
}
for (const resource of resources) {
const key = resource.toString();
const oldStats = this._data[key];
const oldStats = this._data.get(resource);
if (oldStats) {
this._substract(oldStats);
}
const newStats = this._resourceStats(resource);
this._add(newStats);
this._data[key] = newStats;
this._data.set(resource, newStats);
}
}
@@ -124,10 +142,10 @@ export class MarkerService implements IMarkerService {
_serviceBrand: undefined;
private readonly _onMarkerChanged = new Emitter<readonly URI[]>();
private _onMarkerChangedEvent: Event<readonly URI[]> = Event.debounce(this._onMarkerChanged.event, MarkerService._debouncer, 0);
private _byResource: MapMap<IMarker[]> = Object.create(null);
private _byOwner: MapMap<IMarker[]> = Object.create(null);
private _stats: MarkerStats;
readonly onMarkerChanged: Event<readonly URI[]> = Event.debounce(this._onMarkerChanged.event, MarkerService._debouncer, 0);
private readonly _data = new DoubleResourceMap<IMarker[]>();
private readonly _stats: MarkerStats;
constructor() {
this._stats = new MarkerStats(this);
@@ -137,10 +155,6 @@ export class MarkerService implements IMarkerService {
this._stats.dispose();
}
get onMarkerChanged(): Event<readonly URI[]> {
return this._onMarkerChangedEvent;
}
getStatistics(): MarkerStatistics {
return this._stats;
}
@@ -155,12 +169,8 @@ export class MarkerService implements IMarkerService {
if (isFalsyOrEmpty(markerData)) {
// remove marker for this (owner,resource)-tuple
const a = MapMap.remove(this._byResource, resource.toString(), owner);
const b = MapMap.remove(this._byOwner, owner, resource.toString());
if (a !== b) {
throw new Error('invalid marker service state');
}
if (a && b) {
const removed = this._data.delete(resource, owner);
if (removed) {
this._onMarkerChanged.fire([resource]);
}
@@ -173,8 +183,7 @@ export class MarkerService implements IMarkerService {
markers.push(marker);
}
}
MapMap.set(this._byResource, resource.toString(), owner, markers);
MapMap.set(this._byOwner, owner, resource.toString(), markers);
this._data.set(resource, owner, markers);
this._onMarkerChanged.fire([resource]);
}
}
@@ -216,21 +225,15 @@ export class MarkerService implements IMarkerService {
changeAll(owner: string, data: IResourceMarker[]): void {
const changes: URI[] = [];
const map = this._byOwner[owner];
// remove old marker
if (map) {
delete this._byOwner[owner];
for (const resource in map) {
const entry = MapMap.get(this._byResource, resource, owner);
if (entry) {
// remeber what we remove
const [first] = entry;
if (first) {
changes.push(first.resource);
}
// actual remove
MapMap.remove(this._byResource, resource, owner);
const existing = this._data.values(owner);
if (existing) {
for (let data of existing) {
const first = Iterable.first(data);
if (first) {
changes.push(first.resource);
this._data.delete(first.resource, owner);
}
}
}
@@ -239,16 +242,16 @@ export class MarkerService implements IMarkerService {
if (isNonEmptyArray(data)) {
// group by resource
const groups: { [resource: string]: IMarker[] } = Object.create(null);
const groups = new ResourceMap<IMarker[]>();
for (const { resource, marker: markerData } of data) {
const marker = MarkerService._toMarker(owner, resource, markerData);
if (!marker) {
// filter bad markers
continue;
}
const array = groups[resource.toString()];
const array = groups.get(resource);
if (!array) {
groups[resource.toString()] = [marker];
groups.set(resource, [marker]);
changes.push(resource);
} else {
array.push(marker);
@@ -256,9 +259,8 @@ export class MarkerService implements IMarkerService {
}
// insert all
for (const resource in groups) {
MapMap.set(this._byResource, resource, owner, groups[resource]);
MapMap.set(this._byOwner, owner, resource, groups[resource]);
for (const [resource, value] of groups) {
this._data.set(resource, owner, value);
}
}
@@ -277,7 +279,7 @@ export class MarkerService implements IMarkerService {
if (owner && resource) {
// exactly one owner AND resource
const data = MapMap.get(this._byResource, resource.toString(), owner);
const data = this._data.get(resource, owner);
if (!data) {
return [];
} else {
@@ -296,14 +298,12 @@ export class MarkerService implements IMarkerService {
} else if (!owner && !resource) {
// all
const result: IMarker[] = [];
for (const key1 in this._byResource) {
for (const key2 in this._byResource[key1]) {
for (const data of this._byResource[key1][key2]) {
if (MarkerService._accept(data, severities)) {
const newLen = result.push(data);
if (take > 0 && newLen === take) {
return result;
}
for (let markers of this._data.values()) {
for (let data of markers) {
if (MarkerService._accept(data, severities)) {
const newLen = result.push(data);
if (take > 0 && newLen === take) {
return result;
}
}
}
@@ -312,17 +312,10 @@ export class MarkerService implements IMarkerService {
} else {
// of one resource OR owner
const map: { [key: string]: IMarker[] } | undefined = owner
? this._byOwner[owner]
: resource ? this._byResource[resource.toString()] : undefined;
if (!map) {
return [];
}
const iterable = this._data.values(resource ?? owner!);
const result: IMarker[] = [];
for (const key in map) {
for (const data of map[key]) {
for (const markers of iterable) {
for (const data of markers) {
if (MarkerService._accept(data, severities)) {
const newLen = result.push(data);
if (take > 0 && newLen === take) {
@@ -341,16 +334,16 @@ export class MarkerService implements IMarkerService {
// --- event debounce logic
private static _dedupeMap: { [uri: string]: boolean };
private static _dedupeMap: ResourceMap<true>;
private static _debouncer(last: URI[] | undefined, event: readonly URI[]): URI[] {
if (!last) {
MarkerService._dedupeMap = Object.create(null);
MarkerService._dedupeMap = new ResourceMap();
last = [];
}
for (const uri of event) {
if (MarkerService._dedupeMap[uri.toString()] === undefined) {
MarkerService._dedupeMap[uri.toString()] = true;
if (!MarkerService._dedupeMap.has(uri)) {
MarkerService._dedupeMap.set(uri, true);
last.push(uri);
}
}
@@ -703,7 +703,8 @@ export class Menubar {
}
// DevTools focused
if (activeWindow.webContents.isDevToolsFocused()) {
if (activeWindow.webContents.isDevToolsFocused() &&
activeWindow.webContents.devToolsWebContents) {
return contextSpecificHandlers.inDevTools(activeWindow.webContents.devToolsWebContents);
}
+35 -8
View File
@@ -56,6 +56,11 @@ export interface IIconRegistry {
*/
getIcons(): IconContribution[];
/**
* Get the icon for the given id
*/
getIcon(id: string): IconContribution | undefined;
/**
* JSON schema for an object to assign icon values to one of the color contributions.
*/
@@ -130,6 +135,10 @@ class IconRegistry implements IIconRegistry {
return Object.keys(this.iconsById).map(id => this.iconsById[id]);
}
public getIcon(id: string): IconContribution | undefined {
return this.iconsById[id];
}
public getIconSchema(): IJSONSchema {
return this.iconSchema;
}
@@ -139,16 +148,34 @@ class IconRegistry implements IIconRegistry {
}
public toString() {
let sorter = (a: string, b: string) => {
let cat1 = a.indexOf('.') === -1 ? 0 : 1;
let cat2 = b.indexOf('.') === -1 ? 0 : 1;
if (cat1 !== cat2) {
return cat1 - cat2;
const sorter = (i1: IconContribution, i2: IconContribution) => {
const isThemeIcon1 = ThemeIcon.isThemeIcon(i1.defaults);
const isThemeIcon2 = ThemeIcon.isThemeIcon(i2.defaults);
if (isThemeIcon1 !== isThemeIcon2) {
return isThemeIcon1 ? -1 : 1;
}
return a.localeCompare(b);
return i1.id.localeCompare(i2.id);
};
const classNames = (i: IconContribution) => {
while (ThemeIcon.isThemeIcon(i.defaults)) {
i = this.iconsById[i.defaults.id];
}
return `codicon codicon-${i ? i.id : ''}`;
};
return Object.keys(this.iconsById).sort(sorter).map(k => `- \`${k}\`: ${this.iconsById[k].description}`).join('\n');
let reference = [];
let docCss = [];
const contributions = Object.keys(this.iconsById).map(key => this.iconsById[key]);
for (const i of contributions.sort(sorter)) {
reference.push(`|<i class="${classNames(i)}"></i>|${i.id}|${ThemeIcon.isThemeIcon(i.defaults) ? i.defaults.id : ''}|`);
if (!ThemeIcon.isThemeIcon((i.defaults))) {
docCss.push(`.codicon-${i.id}:before { content: "${i.defaults.character}" }`);
}
}
return reference.join('\n') + '\n\n' + docCss.join('\n');
}
}
@@ -186,4 +213,4 @@ iconRegistry.onDidChangeSchema(() => {
});
// setTimeout(_ => console.log(colorRegistry.toString()), 5000);
//setTimeout(_ => console.log(iconRegistry.toString()), 5000);
@@ -167,10 +167,16 @@ export abstract class AbstractSynchroniser extends Disposable {
if (e instanceof UserDataSyncError) {
switch (e.code) {
case UserDataSyncErrorCode.RemotePreconditionFailed:
// Rejected as there is a new remote version. Syncing again,
// Rejected as there is a new remote version. Syncing again...
this.logService.info(`${this.syncResourceLogLabel}: Failed to synchronize as there is a new remote version available. Synchronizing again...`);
// Avoid cache and get latest remote user data - https://github.com/microsoft/vscode/issues/90624
remoteUserData = await this.getRemoteUserData(null);
// Get the latest last sync user data. Because multiples parallel syncs (in Web) could share same last sync data
// and one of them successfully updated remote and last sync state.
lastSyncUserData = await this.getLastSyncUserData();
return this.doSync(remoteUserData, lastSyncUserData);
}
}
@@ -318,7 +318,7 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic
if (!currentWindowsState.lastActiveWindow) {
let activeWindow = this.getLastActiveWindow();
if (!activeWindow || activeWindow.isExtensionDevelopmentHost) {
activeWindow = WindowsMainService.WINDOWS.filter(window => !window.isExtensionDevelopmentHost)[0];
activeWindow = WindowsMainService.WINDOWS.find(window => !window.isExtensionDevelopmentHost);
}
if (activeWindow) {
@@ -327,7 +327,7 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic
}
// 2.) Find extension host window
const extensionHostWindow = WindowsMainService.WINDOWS.filter(window => window.isExtensionDevelopmentHost && !window.isExtensionTestHost)[0];
const extensionHostWindow = WindowsMainService.WINDOWS.find(window => window.isExtensionDevelopmentHost && !window.isExtensionTestHost);
if (extensionHostWindow) {
currentWindowsState.lastPluginDevelopmentHostWindow = this.toWindowState(extensionHostWindow);
}
+1 -1
View File
@@ -168,7 +168,7 @@ function findWindowOnFilePath<W extends IWindowContext>(windows: W[], fileUri: U
export function getLastActiveWindow<W extends IWindowContext>(windows: W[]): W | undefined {
const lastFocusedDate = Math.max.apply(Math, windows.map(window => window.lastFocusTime));
return windows.filter(window => window.lastFocusTime === lastFocusedDate)[0];
return windows.find(window => window.lastFocusTime === lastFocusedDate);
}
export function findWindowOnWorkspace<W extends IWindowContext>(windows: W[], workspace: (IWorkspaceIdentifier | ISingleFolderWorkspaceIdentifier)): W | null {
+45 -2
View File
@@ -7897,7 +7897,7 @@ declare module 'vscode' {
* This will trigger the view to update the changed element/root and its children recursively (if shown).
* To signal that root has changed, do not pass any argument or pass `undefined` or `null`.
*/
onDidChangeTreeData?: Event<T | undefined | null>;
onDidChangeTreeData?: Event<T | undefined | null | void>;
/**
* Get [TreeItem](#TreeItem) representation of the `element`
@@ -10486,6 +10486,23 @@ declare module 'vscode' {
// Properties: see details [here](https://microsoft.github.io/debug-adapter-protocol/specification#Types_Source).
}
/**
* A DebugConfigurationProviderTriggerKind specifies when the `provideDebugConfigurations` method of a `DebugConfigurationProvider` is triggered.
* Currently there are two situations: to provide the initial debug configurations for a newly created launch.json or
* to provide dynamically generated debug configurations when the user asks for them through the UI (e.g. via the "Select and Start Debugging" command).
* A trigger kind is used when registering a `DebugConfigurationProvider` with #debug.registerDebugConfigurationProvider.
*/
export enum DebugConfigurationProviderTriggerKind {
/**
* `DebugConfigurationProvider.provideDebugConfigurations` is called to provide the initial debug configurations for a newly created launch.json.
*/
Initial = 1,
/**
* `DebugConfigurationProvider.provideDebugConfigurations` is called to provide dynamically generated debug configurations when the user asks for them through the UI (e.g. via the "Select and Start Debugging" command).
*/
Dynamic = 2
}
/**
* Namespace for debug functionality.
*/
@@ -10539,13 +10556,19 @@ declare module 'vscode' {
/**
* Register a [debug configuration provider](#DebugConfigurationProvider) for a specific debug type.
* The optional [triggerKind](#DebugConfigurationProviderTriggerKind) can be used to specify when the `provideDebugConfigurations` method of the provider is triggered.
* Currently two trigger kinds are possible: with the value `Initial` (or if no trigger kind argument is given) the `provideDebugConfigurations` method is used to provide the initial debug configurations to be copied into a newly created launch.json.
* With the trigger kind `Dynamic` the `provideDebugConfigurations` method is used to dynamically determine debug configurations to be presented to the user (in addition to the static configurations from the launch.json).
* Please note that the `triggerKind` argument only applies to the `provideDebugConfigurations` method: so the `resolveDebugConfiguration` methods are not affected at all.
* Registering a single provider with resolve methods for different trigger kinds, results in the same resolve methods called multiple times.
* More than one provider can be registered for the same type.
*
* @param type The debug type for which the provider is registered.
* @param provider The [debug configuration provider](#DebugConfigurationProvider) to register.
* @param triggerKind The [trigger](#DebugConfigurationProviderTrigger) for which the 'provideDebugConfiguration' method of the provider is registered. If `triggerKind` is missing, the value `DebugConfigurationProviderTriggerKind.Initial` is assumed.
* @return A [disposable](#Disposable) that unregisters this provider when being disposed.
*/
export function registerDebugConfigurationProvider(debugType: string, provider: DebugConfigurationProvider): Disposable;
export function registerDebugConfigurationProvider(debugType: string, provider: DebugConfigurationProvider, triggerKind?: DebugConfigurationProviderTriggerKind): Disposable;
/**
* Register a [debug adapter descriptor factory](#DebugAdapterDescriptorFactory) for a specific debug type.
@@ -10875,6 +10898,21 @@ declare module 'vscode' {
provideCommentingRanges(document: TextDocument, token: CancellationToken): ProviderResult<Range[]>;
}
/**
* Represents a [comment controller](#CommentController)'s [options](#CommentController.options).
*/
export interface CommentOptions {
/**
* An optional string to show on the comment input box when it's collapsed.
*/
prompt?: string;
/**
* An optional string to show as placeholder in the comment input box when it's focused.
*/
placeHolder?: string;
}
/**
* A comment controller is able to provide [comments](#CommentThread) support to the editor and
* provide users various ways to interact with comments.
@@ -10890,6 +10928,11 @@ declare module 'vscode' {
*/
readonly label: string;
/**
* Comment controller options
*/
options?: CommentOptions;
/**
* Optional commenting range provider. Provide a list [ranges](#Range) which support commenting to any given resource uri.
*
+66 -80
View File
@@ -25,7 +25,7 @@ declare module 'vscode' {
displayName: string;
id: string;
};
scopes: string[]
scopes: string[];
}
/**
@@ -141,12 +141,12 @@ declare module 'vscode' {
* within a session has changed for a provider. Fires with the ids of the providers
* that have had session data change.
*/
export const onDidChangeSessions: Event<{ [providerId: string]: AuthenticationSessionsChangeEvent }>;
export const onDidChangeSessions: Event<{ [providerId: string]: AuthenticationSessionsChangeEvent; }>;
}
//#endregion
//#region Alex - resolvers
//#region @alexdima - resolvers
export interface RemoteAuthorityResolverContext {
resolveAttempt: number;
@@ -160,20 +160,20 @@ declare module 'vscode' {
}
export interface ResolvedOptions {
extensionHostEnv?: { [key: string]: string | null };
extensionHostEnv?: { [key: string]: string | null; };
}
export interface TunnelOptions {
remoteAddress: { port: number, host: string };
remoteAddress: { port: number, host: string; };
// The desired local port. If this port can't be used, then another will be chosen.
localAddressPort?: number;
label?: string;
}
export interface TunnelDescription {
remoteAddress: { port: number, host: string };
remoteAddress: { port: number, host: string; };
//The complete local address(ex. localhost:1234)
localAddress: { port: number, host: string } | string;
localAddress: { port: number, host: string; } | string;
}
export interface Tunnel extends TunnelDescription {
@@ -248,7 +248,7 @@ declare module 'vscode' {
export interface ResourceLabelFormatting {
label: string; // myLabel:/${path}
// TODO@isi
// TODO@isidorn
// eslint-disable-next-line vscode-dts-literal-or-types
separator: '/' | '\\' | '';
tildify?: boolean;
@@ -284,7 +284,7 @@ declare module 'vscode' {
//#region read/write in chunks: https://github.com/microsoft/vscode/issues/84515
export interface FileSystemProvider {
open?(resource: Uri, options: { create: boolean }): number | Thenable<number>;
open?(resource: Uri, options: { create: boolean; }): number | Thenable<number>;
close?(fd: number): void | Thenable<void>;
read?(fd: number, pos: number, data: Uint8Array, offset: number, length: number): number | Thenable<number>;
write?(fd: number, pos: number, data: Uint8Array, offset: number, length: number): number | Thenable<number>;
@@ -326,7 +326,7 @@ declare module 'vscode' {
/**
* A file glob pattern to match file paths against.
* TODO@roblou - merge this with the GlobPattern docs/definition in vscode.d.ts.
* TODO@roblourens merge this with the GlobPattern docs/definition in vscode.d.ts.
* @see [GlobPattern](#GlobPattern)
*/
export type GlobString = string;
@@ -731,42 +731,7 @@ declare module 'vscode' {
//#endregion
//#region debug: https://github.com/microsoft/vscode/issues/88230
/**
* A DebugConfigurationProviderTriggerKind specifies when the `provideDebugConfigurations` method of a `DebugConfigurationProvider` is triggered.
* Currently there are two situations: to provide the initial debug configurations for a newly created launch.json or
* to provide dynamically generated debug configurations when the user asks for them through the UI (e.g. via the "Select and Start Debugging" command).
* A trigger kind is used when registering a `DebugConfigurationProvider` with #debug.registerDebugConfigurationProvider.
*/
export enum DebugConfigurationProviderTriggerKind {
/**
* `DebugConfigurationProvider.provideDebugConfigurations` is called to provide the initial debug configurations for a newly created launch.json.
*/
Initial = 1,
/**
* `DebugConfigurationProvider.provideDebugConfigurations` is called to provide dynamically generated debug configurations when the user asks for them through the UI (e.g. via the "Select and Start Debugging" command).
*/
Dynamic = 2
}
export namespace debug {
/**
* Register a [debug configuration provider](#DebugConfigurationProvider) for a specific debug type.
* The optional [triggerKind](#DebugConfigurationProviderTriggerKind) can be used to specify when the `provideDebugConfigurations` method of the provider is triggered.
* Currently two trigger kinds are possible: with the value `Initial` (or if no trigger kind argument is given) the `provideDebugConfigurations` method is used to provide the initial debug configurations to be copied into a newly created launch.json.
* With the trigger kind `Dynamic` the `provideDebugConfigurations` method is used to dynamically determine debug configurations to be presented to the user (in addition to the static configurations from the launch.json).
* Please note that the `triggerKind` argument only applies to the `provideDebugConfigurations` method: so the `resolveDebugConfiguration` methods are not affected at all.
* Registering a single provider with resolve methods for different trigger kinds, results in the same resolve methods called multiple times.
* More than one provider can be registered for the same type.
*
* @param type The debug type for which the provider is registered.
* @param provider The [debug configuration provider](#DebugConfigurationProvider) to register.
* @param triggerKind The [trigger](#DebugConfigurationProviderTrigger) for which the 'provideDebugConfiguration' method of the provider is registered.
* @return A [disposable](#Disposable) that unregisters this provider when being disposed.
*/
export function registerDebugConfigurationProvider(debugType: string, provider: DebugConfigurationProvider, triggerKind?: DebugConfigurationProviderTriggerKind): Disposable;
}
//#region debug
// deprecated debug API
@@ -809,7 +774,7 @@ declare module 'vscode' {
//#endregion
//#region Joao: SCM validation
//#region @joaomoreno: SCM validation
/**
* Represents the validation type of the Source Control input.
@@ -859,7 +824,7 @@ declare module 'vscode' {
//#endregion
//#region Joao: SCM selected provider
//#region @joaomoreno: SCM selected provider
export interface SourceControl {
@@ -1062,7 +1027,7 @@ declare module 'vscode' {
//#endregion
//#region Joh -> exclusive document filters
//#region @jrieken -> exclusive document filters
export interface DocumentFilter {
exclusive?: boolean;
@@ -1070,7 +1035,7 @@ declare module 'vscode' {
//#endregion
//#region Alex - OnEnter enhancement
//#region @alexdima - OnEnter enhancement
export interface OnEnterRule {
/**
* This rule will only execute if the text above the this line matches this regular expression.
@@ -1579,7 +1544,7 @@ declare module 'vscode' {
//#endregion
//#region Peng: Notebook
//#region @rebornix: Notebook
export enum CellKind {
Markdown = 1,
@@ -1632,7 +1597,7 @@ declare module 'vscode' {
* }
* }
*/
data: { [key: string]: any };
data: { [key: string]: any; };
}
export type CellOutput = CellStreamOutput | CellErrorOutput | CellDisplayOutput;
@@ -1713,6 +1678,8 @@ declare module 'vscode' {
* Defaults to true.
*/
hasExecutionOrder?: boolean;
displayOrder?: GlobPattern[];
}
export interface NotebookDocument {
@@ -1804,13 +1771,54 @@ declare module 'vscode' {
// readonly contentChanges: ReadonlyArray<TextDocumentContentChangeEvent>;
}
export interface NotebookCellData {
readonly cellKind: CellKind;
readonly source: string;
language: string;
outputs: CellOutput[];
metadata: NotebookCellMetadata;
}
export interface NotebookData {
readonly cells: NotebookCellData[];
readonly languages: string[];
readonly metadata: NotebookDocumentMetadata;
}
export interface NotebookContentProvider {
openNotebook(uri: Uri): NotebookData | Promise<NotebookData>;
saveNotebook(document: NotebookDocument, cancellation: CancellationToken): Promise<void>;
saveNotebookAs(targetResource: Uri, document: NotebookDocument, cancellation: CancellationToken): Promise<void>;
readonly onDidChangeNotebook: Event<void>;
// revert?(document: NotebookDocument, cancellation: CancellationToken): Thenable<void>;
// backup?(document: NotebookDocument, cancellation: CancellationToken): Thenable<CustomDocumentBackup>;
/**
* Responsible for filling in outputs for the cell
*/
executeCell(document: NotebookDocument, cell: NotebookCell | undefined, token: CancellationToken): Promise<void>;
}
export namespace notebook {
export function registerNotebookContentProvider(
notebookType: string,
provider: NotebookContentProvider
): Disposable;
export function registerNotebookProvider(
notebookType: string,
provider: NotebookProvider
): Disposable;
export function registerNotebookOutputRenderer(type: string, outputSelector: NotebookOutputSelector, renderer: NotebookOutputRenderer): Disposable;
export function registerNotebookOutputRenderer(
type: string,
outputSelector: NotebookOutputSelector,
renderer: NotebookOutputRenderer
): Disposable;
export const onDidOpenNotebookDocument: Event<NotebookDocument>;
export const onDidCloseNotebookDocument: Event<NotebookDocument>;
// export const onDidChangeVisibleNotebookEditors: Event<NotebookEditor[]>;
// remove activeNotebookDocument, now that there is activeNotebookEditor.document
export let activeNotebookDocument: NotebookDocument | undefined;
@@ -1865,7 +1873,7 @@ declare module 'vscode' {
//#endregion
//#region eamodio - timeline: https://github.com/microsoft/vscode/issues/84297
//#region @eamodio - timeline: https://github.com/microsoft/vscode/issues/84297
export class TimelineItem {
/**
@@ -1888,7 +1896,7 @@ declare module 'vscode' {
/**
* The icon path or [ThemeIcon](#ThemeIcon) for the timeline item.
*/
iconPath?: Uri | { light: Uri; dark: Uri } | ThemeIcon;
iconPath?: Uri | { light: Uri; dark: Uri; } | ThemeIcon;
/**
* A human readable string describing less prominent details of the timeline item.
@@ -1951,7 +1959,7 @@ declare module 'vscode' {
* Use `undefined` to signal that there are no more items to be returned.
*/
readonly cursor: string | undefined;
}
};
/**
* An array of [timeline items](#TimelineItem).
@@ -1969,7 +1977,7 @@ declare module 'vscode' {
* An optional maximum number timeline items or the all timeline items newer (inclusive) than the timestamp or id that should be returned.
* If `undefined` all timeline items should be returned.
*/
limit?: number | { timestamp: number; id?: string };
limit?: number | { timestamp: number; id?: string; };
}
export interface TimelineProvider {
@@ -2033,7 +2041,7 @@ declare module 'vscode' {
*
* - Any code actions of `kind` are returned by the provider.
*/
readonly documentation?: ReadonlyArray<{ readonly kind: CodeActionKind, readonly command: Command }>;
readonly documentation?: ReadonlyArray<{ readonly kind: CodeActionKind, readonly command: Command; }>;
}
//#endregion
@@ -2072,26 +2080,4 @@ declare module 'vscode' {
}
//#endregion
//#region Comment
export interface CommentOptions {
/**
* An optional string to show on the comment input box when it's collapsed.
*/
prompt?: string;
/**
* An optional string to show as placeholder in the comment input box when it's focused.
*/
placeHolder?: string;
}
export interface CommentController {
/**
* Comment controller options
*/
options?: CommentOptions;
}
//#endregion
}
@@ -324,7 +324,7 @@ export class MainThreadAuthentication extends Disposable implements MainThreadAu
}
const remoteConnection = this.remoteAgentService.getConnection();
if (remoteConnection && remoteConnection.remoteAuthority === 'vsonline' && VSO_ALLOWED_EXTENSIONS.includes(extensionId)) {
if (remoteConnection && remoteConnection.remoteAuthority && remoteConnection.remoteAuthority.startsWith('vsonline') && VSO_ALLOWED_EXTENSIONS.includes(extensionId)) {
return true;
}
@@ -448,8 +448,8 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha
}
};
if (supportsResolveDetails) {
provider.resolveCompletionItem = (model, position, suggestion, token) => {
return this._proxy.$resolveCompletionItem(handle, model.uri, position, suggestion._id!, token).then(result => {
provider.resolveCompletionItem = (suggestion, token) => {
return this._proxy.$resolveCompletionItem(handle, suggestion._id!, token).then(result => {
if (!result) {
return suggestion;
}
@@ -7,7 +7,7 @@ import { extHostNamedCustomer } from 'vs/workbench/api/common/extHostCustomers';
import { MainContext, MainThreadNotebookShape, NotebookExtensionDescription, IExtHostContext, ExtHostNotebookShape, ExtHostContext } from '../common/extHost.protocol';
import { Disposable } from 'vs/base/common/lifecycle';
import { URI, UriComponents } from 'vs/base/common/uri';
import { INotebookService, IMainNotebookController } from 'vs/workbench/contrib/notebook/browser/notebookService';
import { INotebookService, IMainNotebookController } from 'vs/workbench/contrib/notebook/common/notebookService';
import { INotebookTextModel, INotebookMimeTypeSelector, NOTEBOOK_DISPLAY_ORDER, NotebookCellOutputsSplice, CellKind, NotebookDocumentMetadata, NotebookCellMetadata, ICellEditOperation, ACCESSIBLE_NOTEBOOK_DISPLAY_ORDER } from 'vs/workbench/contrib/notebook/common/notebookCommon';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { NotebookTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookTextModel';
@@ -294,7 +294,7 @@ export class MainThreadNotebookController implements IMainNotebookController {
}
}
async save(uri: URI): Promise<boolean> {
return this._proxy.$saveNotebook(this._viewType, uri);
async save(uri: URI, token: CancellationToken): Promise<boolean> {
return this._proxy.$saveNotebook(this._viewType, uri, token);
}
}
@@ -409,6 +409,7 @@ class ViewsExtensionHandler implements IWorkbenchContribution {
name: item.name,
ctorDescriptor: new SyncDescriptor(TreeViewPane),
when: ContextKeyExpr.deserialize(item.when),
containerIcon: viewContainer?.icon,
canToggleVisibility: true,
canMoveView: true,
treeView: this.instantiationService.createInstance(CustomTreeView, item.id, item.name),
@@ -327,7 +327,7 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
// namespace: languages
const languages: typeof vscode.languages = {
createDiagnosticCollection(name?: string): vscode.DiagnosticCollection {
return extHostDiagnostics.createDiagnosticCollection(name);
return extHostDiagnostics.createDiagnosticCollection(extension.identifier, name);
},
get onDidChangeDiagnostics() {
return extHostDiagnostics.onDidChangeDiagnostics;
@@ -923,10 +923,22 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
// namespace: notebook
const notebook: typeof vscode.notebook = {
get onDidOpenNotebookDocument(): Event<vscode.NotebookDocument> {
checkProposedApiEnabled(extension);
return extHostNotebook.onDidOpenNotebookDocument;
},
get onDidCloseNotebookDocument(): Event<vscode.NotebookDocument> {
checkProposedApiEnabled(extension);
return extHostNotebook.onDidCloseNotebookDocument;
},
registerNotebookProvider: (viewType: string, provider: vscode.NotebookProvider) => {
checkProposedApiEnabled(extension);
return extHostNotebook.registerNotebookProvider(extension, viewType, provider);
},
registerNotebookContentProvider: (viewType: string, provider: vscode.NotebookContentProvider) => {
checkProposedApiEnabled(extension);
return extHostNotebook.registerNotebookContentProvider(extension, viewType, provider);
},
registerNotebookOutputRenderer: (type: string, outputFilter: vscode.NotebookOutputSelector, renderer: vscode.NotebookOutputRenderer) => {
checkProposedApiEnabled(extension);
return extHostNotebook.registerNotebookOutputRenderer(type, extension, outputFilter, renderer);
@@ -1318,7 +1318,7 @@ export interface ExtHostLanguageFeaturesShape {
$releaseDocumentSemanticTokens(handle: number, semanticColoringResultId: number): void;
$provideDocumentRangeSemanticTokens(handle: number, resource: UriComponents, range: IRange, token: CancellationToken): Promise<VSBuffer | null>;
$provideCompletionItems(handle: number, resource: UriComponents, position: IPosition, context: modes.CompletionContext, token: CancellationToken): Promise<ISuggestResultDto | undefined>;
$resolveCompletionItem(handle: number, resource: UriComponents, position: IPosition, id: ChainedCacheId, token: CancellationToken): Promise<ISuggestDataDto | undefined>;
$resolveCompletionItem(handle: number, id: ChainedCacheId, token: CancellationToken): Promise<ISuggestDataDto | undefined>;
$releaseCompletionItems(handle: number, id: number): void;
$provideSignatureHelp(handle: number, resource: UriComponents, position: IPosition, context: modes.SignatureHelpContext, token: CancellationToken): Promise<ISignatureHelpDto | undefined>;
$releaseSignatureHelp(handle: number, id: number): void;
@@ -1545,7 +1545,7 @@ export interface INotebookEditorPropertiesChangeData {
export interface ExtHostNotebookShape {
$resolveNotebook(viewType: string, uri: UriComponents): Promise<number | undefined>;
$executeNotebook(viewType: string, uri: UriComponents, cellHandle: number | undefined, token: CancellationToken): Promise<void>;
$saveNotebook(viewType: string, uri: UriComponents): Promise<boolean>;
$saveNotebook(viewType: string, uri: UriComponents, token: CancellationToken): Promise<boolean>;
$updateActiveEditor(viewType: string, uri: UriComponents): Promise<void>;
$destoryNotebookDocument(viewType: string, uri: UriComponents): Promise<boolean>;
$acceptDisplayOrder(displayOrder: INotebookDisplayOrder): void;
@@ -13,25 +13,21 @@ import * as converter from './extHostTypeConverters';
import { mergeSort } from 'vs/base/common/arrays';
import { Event, Emitter } from 'vs/base/common/event';
import { ILogService } from 'vs/platform/log/common/log';
import { ResourceMap } from 'vs/base/common/map';
import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions';
export class DiagnosticCollection implements vscode.DiagnosticCollection {
private readonly _name: string;
private readonly _owner: string;
private readonly _maxDiagnosticsPerFile: number;
private readonly _onDidChangeDiagnostics: Emitter<(vscode.Uri | string)[]>;
private readonly _proxy: MainThreadDiagnosticsShape | undefined;
private _isDisposed = false;
private _data = new Map<string, vscode.Diagnostic[]>();
private _data = new ResourceMap<vscode.Diagnostic[]>();
constructor(name: string, owner: string, maxDiagnosticsPerFile: number, proxy: MainThreadDiagnosticsShape | undefined, onDidChangeDiagnostics: Emitter<(vscode.Uri | string)[]>) {
this._name = name;
this._owner = owner;
this._maxDiagnosticsPerFile = maxDiagnosticsPerFile;
this._proxy = proxy;
this._onDidChangeDiagnostics = onDidChangeDiagnostics;
}
constructor(
private readonly _name: string,
private readonly _owner: string,
private readonly _maxDiagnosticsPerFile: number,
private readonly _proxy: MainThreadDiagnosticsShape | undefined,
private readonly _onDidChangeDiagnostics: Emitter<vscode.Uri[]>
) { }
dispose(): void {
if (!this._isDisposed) {
@@ -73,7 +69,7 @@ export class DiagnosticCollection implements vscode.DiagnosticCollection {
}
// update single row
this._data.set(first.toString(), diagnostics.slice());
this._data.set(first, diagnostics.slice());
toSync = [first];
} else if (Array.isArray(first)) {
@@ -87,8 +83,8 @@ export class DiagnosticCollection implements vscode.DiagnosticCollection {
for (const tuple of first) {
const [uri, diagnostics] = tuple;
if (!lastUri || uri.toString() !== lastUri.toString()) {
if (lastUri && this._data.get(lastUri.toString())!.length === 0) {
this._data.delete(lastUri.toString());
if (lastUri && this._data.get(lastUri)!.length === 0) {
this._data.delete(lastUri);
}
lastUri = uri;
toSync.push(uri);
@@ -120,7 +116,7 @@ export class DiagnosticCollection implements vscode.DiagnosticCollection {
const entries: [URI, IMarkerData[]][] = [];
for (let uri of toSync) {
let marker: IMarkerData[] = [];
const diagnostics = this._data.get(uri.toString());
const diagnostics = this._data.get(uri);
if (diagnostics) {
// no more than N diagnostics per file
@@ -160,7 +156,7 @@ export class DiagnosticCollection implements vscode.DiagnosticCollection {
delete(uri: vscode.Uri): void {
this._checkDisposed();
this._onDidChangeDiagnostics.fire([uri]);
this._data.delete(uri.toString());
this._data.delete(uri);
if (this._proxy) {
this._proxy.$changeMany(this._owner, [[uri, undefined]]);
}
@@ -177,15 +173,14 @@ export class DiagnosticCollection implements vscode.DiagnosticCollection {
forEach(callback: (uri: URI, diagnostics: ReadonlyArray<vscode.Diagnostic>, collection: DiagnosticCollection) => any, thisArg?: any): void {
this._checkDisposed();
this._data.forEach((value, key) => {
const uri = URI.parse(key);
this._data.forEach((value, uri) => {
callback.apply(thisArg, [uri, this.get(uri), this]);
});
}
get(uri: URI): ReadonlyArray<vscode.Diagnostic> {
this._checkDisposed();
const result = this._data.get(uri.toString());
const result = this._data.get(uri);
if (Array.isArray(result)) {
return <ReadonlyArray<vscode.Diagnostic>>Object.freeze(result.slice(0));
}
@@ -194,7 +189,7 @@ export class DiagnosticCollection implements vscode.DiagnosticCollection {
has(uri: URI): boolean {
this._checkDisposed();
return Array.isArray(this._data.get(uri.toString()));
return Array.isArray(this._data.get(uri));
}
private _checkDisposed() {
@@ -221,7 +216,7 @@ export class ExtHostDiagnostics implements ExtHostDiagnosticsShape {
private readonly _proxy: MainThreadDiagnosticsShape;
private readonly _collections = new Map<string, DiagnosticCollection>();
private readonly _onDidChangeDiagnostics = new Emitter<(vscode.Uri | string)[]>();
private readonly _onDidChangeDiagnostics = new Emitter<vscode.Uri[]>();
static _debouncer(last: (vscode.Uri | string)[] | undefined, current: (vscode.Uri | string)[]): (vscode.Uri | string)[] {
if (!last) {
@@ -257,8 +252,25 @@ export class ExtHostDiagnostics implements ExtHostDiagnosticsShape {
this._proxy = mainContext.getProxy(MainContext.MainThreadDiagnostics);
}
createDiagnosticCollection(name?: string): vscode.DiagnosticCollection {
let { _collections, _proxy, _onDidChangeDiagnostics } = this;
createDiagnosticCollection(extensionId: ExtensionIdentifier, name?: string): vscode.DiagnosticCollection {
const { _collections, _proxy, _onDidChangeDiagnostics, _logService } = this;
const loggingProxy = new class implements MainThreadDiagnosticsShape {
$changeMany(owner: string, entries: [UriComponents, IMarkerData[] | undefined][]): void {
_proxy.$changeMany(owner, entries);
_logService.trace('[DiagnosticCollection] change many (extension, owner, uris)', extensionId.value, owner, entries.length === 0 ? 'CLEARING' : entries);
}
$clear(owner: string): void {
_proxy.$clear(owner);
_logService.trace('[DiagnosticCollection] remove all (extension, owner)', extensionId.value, owner);
}
dispose(): void {
_proxy.dispose();
}
};
let owner: string;
if (!name) {
name = '_generated_diagnostic_collection_name_#' + ExtHostDiagnostics._idPool++;
@@ -274,7 +286,7 @@ export class ExtHostDiagnostics implements ExtHostDiagnosticsShape {
const result = new class extends DiagnosticCollection {
constructor() {
super(name!, owner, ExtHostDiagnostics._maxDiagnosticsPerFile, _proxy, _onDidChangeDiagnostics);
super(name!, owner, ExtHostDiagnostics._maxDiagnosticsPerFile, loggingProxy, _onDidChangeDiagnostics);
_collections.set(owner, this);
}
dispose() {
@@ -5,7 +5,6 @@
import { Event } from 'vs/base/common/event';
import { URI, UriComponents } from 'vs/base/common/uri';
import { sequence } from 'vs/base/common/async';
import { illegalState } from 'vs/base/common/errors';
import { ExtHostDocumentSaveParticipantShape, MainThreadTextEditorsShape, IWorkspaceEditDto } from 'vs/workbench/api/common/extHost.protocol';
import { TextEdit } from 'vs/workbench/api/common/extHostTypes';
@@ -48,26 +47,27 @@ export class ExtHostDocumentSaveParticipant implements ExtHostDocumentSavePartic
};
}
$participateInSave(data: UriComponents, reason: SaveReason): Promise<boolean[]> {
async $participateInSave(data: UriComponents, reason: SaveReason): Promise<boolean[]> {
const resource = URI.revive(data);
const entries = this._callbacks.toArray();
let didTimeout = false;
const didTimeoutHandle = setTimeout(() => didTimeout = true, this._thresholds.timeout);
const promise = sequence(entries.map(listener => {
return () => {
const results: boolean[] = [];
try {
for (let listener of [...this._callbacks]) { // copy to prevent concurrent modifications
if (didTimeout) {
// timeout - no more listeners
return Promise.resolve();
break;
}
const document = this._documents.getDocument(resource);
return this._deliverEventAsyncAndBlameBadListeners(listener, <any>{ document, reason: TextDocumentSaveReason.to(reason) });
};
}));
return promise.finally(() => clearTimeout(didTimeoutHandle));
const success = await this._deliverEventAsyncAndBlameBadListeners(listener, <any>{ document, reason: TextDocumentSaveReason.to(reason) });
results.push(success);
}
} finally {
clearTimeout(didTimeoutHandle);
}
return results;
}
private _deliverEventAsyncAndBlameBadListeners([listener, thisArg, extension]: Listener, stubEvent: vscode.TextDocumentWillSaveEvent): Promise<any> {
@@ -7,7 +7,7 @@ import { URI, UriComponents } from 'vs/base/common/uri';
import { mixin } from 'vs/base/common/objects';
import type * as vscode from 'vscode';
import * as typeConvert from 'vs/workbench/api/common/extHostTypeConverters';
import { Range, Disposable, CompletionList, SnippetString, CodeActionKind, SymbolInformation, DocumentSymbol, SemanticTokensEdits } from 'vs/workbench/api/common/extHostTypes';
import { Range, Disposable, CompletionList, SnippetString, CodeActionKind, SymbolInformation, DocumentSymbol, SemanticTokensEdits, SemanticTokens, SemanticTokensEdit } from 'vs/workbench/api/common/extHostTypes';
import { ISingleEditOperation } from 'vs/editor/common/model';
import * as modes from 'vs/editor/common/modes';
import { ExtHostDocuments } from 'vs/workbench/api/common/extHostDocuments';
@@ -676,6 +676,13 @@ class SemanticTokensPreviousResult {
) { }
}
type RelaxedSemanticTokens = { readonly resultId?: string; readonly data: number[]; };
type RelaxedSemanticTokensEdit = { readonly start: number; readonly deleteCount: number; readonly data?: number[]; };
type RelaxedSemanticTokensEdits = { readonly resultId?: string; readonly edits: RelaxedSemanticTokensEdit[]; };
type ProvidedSemanticTokens = vscode.SemanticTokens | RelaxedSemanticTokens;
type ProvidedSemanticTokensEdits = vscode.SemanticTokensEdits | RelaxedSemanticTokensEdits;
export class DocumentSemanticTokensAdapter {
private readonly _previousResults: Map<number, SemanticTokensPreviousResult>;
@@ -696,13 +703,14 @@ export class DocumentSemanticTokensAdapter {
return this._provider.provideDocumentSemanticTokensEdits(doc, previousResult.resultId, token);
}
return this._provider.provideDocumentSemanticTokens(doc, token);
}).then(value => {
}).then((value: ProvidedSemanticTokens | ProvidedSemanticTokensEdits | null | undefined) => {
if (previousResult) {
this._previousResults.delete(previousResultId);
}
if (!value) {
return null;
}
value = DocumentSemanticTokensAdapter._fixProvidedSemanticTokens(value);
return this._send(DocumentSemanticTokensAdapter._convertToEdits(previousResult, value), value);
});
}
@@ -711,12 +719,40 @@ export class DocumentSemanticTokensAdapter {
this._previousResults.delete(semanticColoringResultId);
}
private static _isSemanticTokens(v: vscode.SemanticTokens | vscode.SemanticTokensEdits): v is vscode.SemanticTokens {
return v && !!((v as vscode.SemanticTokens).data);
private static _fixProvidedSemanticTokens(v: ProvidedSemanticTokens | ProvidedSemanticTokensEdits): vscode.SemanticTokens | vscode.SemanticTokensEdits {
if (DocumentSemanticTokensAdapter._isSemanticTokens(v)) {
if (DocumentSemanticTokensAdapter._isCorrectSemanticTokens(v)) {
return v;
}
return new SemanticTokens(new Uint32Array(v.data), v.resultId);
} else if (DocumentSemanticTokensAdapter._isSemanticTokensEdits(v)) {
if (DocumentSemanticTokensAdapter._isCorrectSemanticTokensEdits(v)) {
return v;
}
return new SemanticTokensEdits(v.edits.map(edit => new SemanticTokensEdit(edit.start, edit.deleteCount, edit.data ? new Uint32Array(edit.data) : edit.data as undefined)), v.resultId); // {{SQL CARBON EDIT}} strict-null-checks
}
return v;
}
private static _isSemanticTokensEdits(v: vscode.SemanticTokens | vscode.SemanticTokensEdits): v is vscode.SemanticTokensEdits {
return v && Array.isArray((v as vscode.SemanticTokensEdits).edits);
private static _isSemanticTokens(v: ProvidedSemanticTokens | ProvidedSemanticTokensEdits): v is ProvidedSemanticTokens {
return v && !!((v as ProvidedSemanticTokens).data);
}
private static _isCorrectSemanticTokens(v: ProvidedSemanticTokens): v is vscode.SemanticTokens {
return (v.data instanceof Uint32Array);
}
private static _isSemanticTokensEdits(v: ProvidedSemanticTokens | ProvidedSemanticTokensEdits): v is ProvidedSemanticTokensEdits {
return v && Array.isArray((v as ProvidedSemanticTokensEdits).edits);
}
private static _isCorrectSemanticTokensEdits(v: ProvidedSemanticTokensEdits): v is vscode.SemanticTokensEdits {
for (const edit of v.edits) {
if (!(edit.data instanceof Uint32Array)) {
return false;
}
}
return true;
}
private static _convertToEdits(previousResult: SemanticTokensPreviousResult | null | undefined, newResult: vscode.SemanticTokens | vscode.SemanticTokensEdits): vscode.SemanticTokens | vscode.SemanticTokensEdits {
@@ -876,33 +912,30 @@ class SuggestAdapter {
for (let i = 0; i < list.items.length; i++) {
const item = list.items[i];
// check for bad completion item first
if (this._validateCompletionItem(item, pos)) {
const dto = this._convertCompletionItem(item, [pid, i], insertRange, replaceRange);
completions.push(dto);
}
const dto = this._convertCompletionItem(item, [pid, i], insertRange, replaceRange);
completions.push(dto);
}
return result;
}
async resolveCompletionItem(_resource: URI, position: IPosition, id: extHostProtocol.ChainedCacheId, token: CancellationToken): Promise<extHostProtocol.ISuggestDataDto | undefined> {
async resolveCompletionItem(id: extHostProtocol.ChainedCacheId, token: CancellationToken): Promise<extHostProtocol.ISuggestDataDto | undefined> {
if (typeof this._provider.resolveCompletionItem !== 'function') {
return Promise.resolve(undefined);
return undefined;
}
const item = this._cache.get(...id);
if (!item) {
return Promise.resolve(undefined);
return undefined;
}
const pos = typeConvert.Position.to(position);
const _mustNotChange = SuggestAdapter._mustNotChangeHash(item);
const _mayNotChange = SuggestAdapter._mayNotChangeHash(item);
const resolvedItem = await asPromise(() => this._provider.resolveCompletionItem!(item, token));
if (!resolvedItem || !this._validateCompletionItem(resolvedItem, pos)) {
if (!resolvedItem) {
return undefined;
}
@@ -952,14 +985,14 @@ class SuggestAdapter {
//
x: id,
//
[extHostProtocol.ISuggestDataDtoField.label]: item.label,
[extHostProtocol.ISuggestDataDtoField.label]: item.label ?? '',
[extHostProtocol.ISuggestDataDtoField.label2]: item.label2,
[extHostProtocol.ISuggestDataDtoField.kind]: item.kind !== undefined ? typeConvert.CompletionItemKind.from(item.kind) : undefined,
[extHostProtocol.ISuggestDataDtoField.kindModifier]: item.tags && item.tags.map(typeConvert.CompletionItemTag.from),
[extHostProtocol.ISuggestDataDtoField.detail]: item.detail,
[extHostProtocol.ISuggestDataDtoField.documentation]: typeof item.documentation === 'undefined' ? undefined : typeConvert.MarkdownString.fromStrict(item.documentation),
[extHostProtocol.ISuggestDataDtoField.sortText]: item.sortText,
[extHostProtocol.ISuggestDataDtoField.filterText]: item.filterText,
[extHostProtocol.ISuggestDataDtoField.sortText]: item.sortText !== item.label ? item.sortText : undefined,
[extHostProtocol.ISuggestDataDtoField.filterText]: item.filterText !== item.label ? item.filterText : undefined,
[extHostProtocol.ISuggestDataDtoField.preselect]: item.preselect || undefined,
[extHostProtocol.ISuggestDataDtoField.insertTextRules]: item.keepWhitespace ? modes.CompletionItemInsertTextRule.KeepWhitespace : 0,
[extHostProtocol.ISuggestDataDtoField.commitCharacters]: item.commitCharacters,
@@ -1003,31 +1036,6 @@ class SuggestAdapter {
return result;
}
private _validateCompletionItem(item: vscode.CompletionItem, position: vscode.Position): boolean {
if (typeof item.label !== 'string' || item.label.length === 0) {
this._logService.warn('INVALID text edit -> must have at least a label');
return false;
}
if (Range.isRange(item.range)) {
if (!item.range.isSingleLine || item.range.start.line !== position.line) {
this._logService.trace('INVALID range -> must be single line and on the same line');
return false;
}
} else if (item.range) {
if (!item.range.inserting.isSingleLine || item.range.inserting.start.line !== position.line
|| !item.range.replacing.isSingleLine || item.range.replacing.start.line !== position.line
|| !item.range.inserting.start.isEqual(item.range.replacing.start)
|| !item.range.replacing.contains(item.range.inserting)
) {
this._logService.trace('INVALID range -> must be single line, on the same line, insert range must be a prefix of replace range');
return false;
}
}
return true;
}
private static _mustNotChangeHash(item: vscode.CompletionItem) {
const res = JSON.stringify([item.label, item.sortText, item.filterText, item.insertText, item.range]);
return res;
@@ -1781,8 +1789,8 @@ export class ExtHostLanguageFeatures implements extHostProtocol.ExtHostLanguageF
return this._withAdapter(handle, SuggestAdapter, adapter => adapter.provideCompletionItems(URI.revive(resource), position, context, token), undefined);
}
$resolveCompletionItem(handle: number, resource: UriComponents, position: IPosition, id: extHostProtocol.ChainedCacheId, token: CancellationToken): Promise<extHostProtocol.ISuggestDataDto | undefined> {
return this._withAdapter(handle, SuggestAdapter, adapter => adapter.resolveCompletionItem(URI.revive(resource), position, id, token), undefined);
$resolveCompletionItem(handle: number, id: extHostProtocol.ChainedCacheId, token: CancellationToken): Promise<extHostProtocol.ISuggestDataDto | undefined> {
return this._withAdapter(handle, SuggestAdapter, adapter => adapter.resolveCompletionItem(id, token), undefined);
}
$releaseCompletionItems(handle: number, id: number): void {
+113 -11
View File
@@ -626,12 +626,13 @@ export class ExtHostNotebookController implements ExtHostNotebookShape, ExtHostN
private readonly _proxy: MainThreadNotebookShape;
private readonly _notebookProviders = new Map<string, { readonly provider: vscode.NotebookProvider, readonly extension: IExtensionDescription; }>();
private readonly _notebookContentProviders = new Map<string, { readonly provider: vscode.NotebookContentProvider, readonly extension: IExtensionDescription; }>();
private readonly _documents = new Map<string, ExtHostNotebookDocument>();
private readonly _editors = new Map<string, { editor: ExtHostNotebookEditor, onDidReceiveMessage: Emitter<any> }>();
private readonly _editors = new Map<string, { editor: ExtHostNotebookEditor, onDidReceiveMessage: Emitter<any>; }>();
private readonly _notebookOutputRenderers = new Map<number, ExtHostNotebookOutputRenderer>();
private readonly _onDidChangeNotebookDocument = new Emitter<{ document: ExtHostNotebookDocument, changes: NotebookCellsChangedEvent[] }>();
readonly onDidChangeNotebookDocument: Event<{ document: ExtHostNotebookDocument, changes: NotebookCellsChangedEvent[] }> = this._onDidChangeNotebookDocument.event;
private readonly _onDidChangeNotebookDocument = new Emitter<{ document: ExtHostNotebookDocument, changes: NotebookCellsChangedEvent[]; }>();
readonly onDidChangeNotebookDocument: Event<{ document: ExtHostNotebookDocument, changes: NotebookCellsChangedEvent[]; }> = this._onDidChangeNotebookDocument.event;
private _outputDisplayOrder: INotebookDisplayOrder | undefined;
@@ -651,6 +652,11 @@ export class ExtHostNotebookController implements ExtHostNotebookShape, ExtHostN
return this._activeNotebookEditor;
}
private _onDidOpenNotebookDocument = new Emitter<vscode.NotebookDocument>();
onDidOpenNotebookDocument: Event<vscode.NotebookDocument> = this._onDidOpenNotebookDocument.event;
private _onDidCloseNotebookDocument = new Emitter<vscode.NotebookDocument>();
onDidCloseNotebookDocument: Event<vscode.NotebookDocument> = this._onDidCloseNotebookDocument.event;
constructor(mainContext: IMainContext, commands: ExtHostCommands, private _documentsAndEditors: ExtHostDocumentsAndEditors) {
this._proxy = mainContext.getProxy(MainContext.MainThreadNotebook);
@@ -718,7 +724,82 @@ export class ExtHostNotebookController implements ExtHostNotebookShape, ExtHostN
});
}
registerNotebookContentProvider(
extension: IExtensionDescription,
viewType: string,
provider: vscode.NotebookContentProvider,
): vscode.Disposable {
if (this._notebookProviders.has(viewType)) {
throw new Error(`Notebook provider for '${viewType}' already registered`);
}
this._notebookContentProviders.set(viewType, { extension, provider });
this._proxy.$registerNotebookProvider({ id: extension.identifier, location: extension.extensionLocation }, viewType);
return new VSCodeDisposable(() => {
this._notebookContentProviders.delete(viewType);
this._proxy.$unregisterNotebookProvider(viewType);
});
}
async _resolveNotebookFromContentProvider(viewType: string, uri: UriComponents): Promise<number | undefined> {
let provider = this._notebookContentProviders.get(viewType);
if (provider) {
const revivedUri = URI.revive(uri);
if (!this._documents.has(revivedUri.toString())) {
let document = new ExtHostNotebookDocument(this._proxy, this._documentsAndEditors, viewType, revivedUri, this);
await this._proxy.$createNotebookDocument(
document.handle,
viewType,
uri
);
this._documents.set(revivedUri.toString(), document);
}
const onDidReceiveMessage = new Emitter<any>();
let editor = new ExtHostNotebookEditor(
viewType,
`${ExtHostNotebookController._handlePool++}`,
revivedUri,
this._proxy,
onDidReceiveMessage,
this._documents.get(revivedUri.toString())!,
this._documentsAndEditors
);
this._editors.set(revivedUri.toString(), { editor, onDidReceiveMessage });
const data = await provider.provider.openNotebook(revivedUri);
editor.document.languages = data.languages;
editor.document.metadata = {
...notebookDocumentMetadataDefaults,
...data.metadata
};
await editor.edit(editBuilder => {
for (let i = 0; i < data.cells.length; i++) {
const cell = data.cells[i];
editBuilder.insert(0, cell.source, cell.language, cell.cellKind, cell.outputs, cell.metadata);
}
});
this._onDidOpenNotebookDocument.fire(editor.document);
return editor.document.handle;
} else {
return Promise.resolve(undefined);
}
}
async $resolveNotebook(viewType: string, uri: UriComponents): Promise<number | undefined> {
let notebookFromNotebookContentProvider = await this._resolveNotebookFromContentProvider(viewType, uri);
if (notebookFromNotebookContentProvider !== undefined) {
return notebookFromNotebookContentProvider;
}
let provider = this._notebookProviders.get(viewType);
if (provider) {
@@ -755,25 +836,45 @@ export class ExtHostNotebookController implements ExtHostNotebookShape, ExtHostN
}
async $executeNotebook(viewType: string, uri: UriComponents, cellHandle: number | undefined, token: CancellationToken): Promise<void> {
let provider = this._notebookProviders.get(viewType);
if (!provider) {
return;
}
let document = this._documents.get(URI.revive(uri).toString());
if (!document) {
return;
}
if (this._notebookContentProviders.has(viewType)) {
let cell = cellHandle !== undefined ? document.getCell(cellHandle) : undefined;
return this._notebookContentProviders.get(viewType)!.provider.executeCell(document, cell, token);
}
let provider = this._notebookProviders.get(viewType);
if (!provider) {
return;
}
let cell = cellHandle !== undefined ? document.getCell(cellHandle) : undefined;
return provider.provider.executeCell(document!, cell, token);
}
async $saveNotebook(viewType: string, uri: UriComponents): Promise<boolean> {
let provider = this._notebookProviders.get(viewType);
async $saveNotebook(viewType: string, uri: UriComponents, token: CancellationToken): Promise<boolean> {
let document = this._documents.get(URI.revive(uri).toString());
if (!document) {
return false;
}
if (this._notebookContentProviders.has(viewType)) {
try {
await this._notebookContentProviders.get(viewType)!.provider.saveNotebook(document, token);
} catch (e) {
return false;
}
return true;
}
let provider = this._notebookProviders.get(viewType);
if (provider && document) {
return await provider.provider.save(document);
@@ -799,6 +900,7 @@ export class ExtHostNotebookController implements ExtHostNotebookShape, ExtHostN
if (document) {
document.dispose();
this._documents.delete(URI.revive(uri).toString());
this._onDidCloseNotebookDocument.fire(document);
}
let editor = this._editors.get(URI.revive(uri).toString());
+10 -11
View File
@@ -159,17 +159,16 @@ export class ExtHostQuickOpen implements ExtHostQuickOpenShape {
// ---- workspace folder picker
showWorkspaceFolderPick(options?: WorkspaceFolderPickOptions, token = CancellationToken.None): Promise<WorkspaceFolder | undefined> {
return this._commands.executeCommand<WorkspaceFolder>('_workbench.pickWorkspaceFolder', [options]).then(async (selectedFolder: WorkspaceFolder) => {
if (!selectedFolder) {
return undefined;
}
const workspaceFolders = await this._workspace.getWorkspaceFolders2();
if (!workspaceFolders) {
return undefined;
}
return workspaceFolders.filter(folder => folder.uri.toString() === selectedFolder.uri.toString())[0];
});
async showWorkspaceFolderPick(options?: WorkspaceFolderPickOptions, token = CancellationToken.None): Promise<WorkspaceFolder | undefined> {
const selectedFolder = await this._commands.executeCommand<WorkspaceFolder>('_workbench.pickWorkspaceFolder', [options]);
if (!selectedFolder) {
return undefined;
}
const workspaceFolders = await this._workspace.getWorkspaceFolders2();
if (!workspaceFolders) {
return undefined;
}
return workspaceFolders.find(folder => folder.uri.toString() === selectedFolder.uri.toString());
}
// ---- QuickInput
@@ -11,7 +11,6 @@ import { nullExtensionDescription } from 'vs/workbench/services/extensions/commo
import { ExtensionDescriptionRegistry } from 'vs/workbench/services/extensions/common/extensionDescriptionRegistry';
import * as vscode from 'vscode';
import { ExtensionIdentifier, IExtensionDescription } from 'vs/platform/extensions/common/extensions';
import { endsWith } from 'vs/base/common/strings';
import { IExtensionApiFactory } from 'vs/workbench/api/common/extHost.api.impl';
import { IExtHostRpcService } from 'vs/workbench/api/common/extHostRpcService';
import { IExtHostInitDataService } from 'vs/workbench/api/common/extHostInitDataService';
@@ -196,7 +195,7 @@ class KeytarNodeModuleFactory implements INodeModuleFactory {
return undefined;
}
const sep = length - 7;
if ((name.charAt(sep) === '/' || name.charAt(sep) === '\\') && endsWith(name, 'keytar')) {
if ((name.charAt(sep) === '/' || name.charAt(sep) === '\\') && name.endsWith('keytar')) {
name = name.replace(/\\/g, '/');
if (this.alternativeNames.has(name)) {
return 'keytar';
@@ -155,7 +155,7 @@ export class ExtHostTreeViews implements ExtHostTreeViewsShape {
}
}
type Root = null | undefined;
export type Root = null | undefined | void; // {{SQL CARBON EDIT}} export interface
type TreeData<T> = { message: boolean, element: T | Root | false };
export interface TreeNode extends IDisposable { // {{SQL CARBON EDIT}} export interface
@@ -10,7 +10,7 @@ import { IJSONSchema } from 'vs/base/common/jsonSchema';
import { forEach } from 'vs/base/common/collections';
import { IExtensionPointUser, ExtensionMessageCollector, ExtensionsRegistry } from 'vs/workbench/services/extensions/common/extensionsRegistry';
import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
import { MenuId, MenuRegistry, ILocalizedString, IMenuItem } from 'vs/platform/actions/common/actions';
import { MenuId, MenuRegistry, ILocalizedString, IMenuItem, ICommandAction } from 'vs/platform/actions/common/actions';
import { URI } from 'vs/base/common/uri';
import { DisposableStore } from 'vs/base/common/lifecycle';
import { ThemeIcon } from 'vs/platform/theme/common/themeService';
@@ -387,7 +387,7 @@ export const commandsExtensionPoint = ExtensionsRegistry.registerExtensionPoint<
commandsExtensionPoint.setHandler(extensions => {
function handleCommand(userFriendlyCommand: schema.IUserFriendlyCommand, extension: IExtensionPointUser<any>) {
function handleCommand(userFriendlyCommand: schema.IUserFriendlyCommand, extension: IExtensionPointUser<any>, bucket: ICommandAction[]) {
if (!schema.isValidCommand(userFriendlyCommand, extension.collector)) {
return;
@@ -411,29 +411,30 @@ commandsExtensionPoint.setHandler(extensions => {
if (MenuRegistry.getCommand(command)) {
extension.collector.info(localize('dup', "Command `{0}` appears multiple times in the `commands` section.", userFriendlyCommand.command));
}
const registration = MenuRegistry.addCommand({
bucket.push({
id: command,
title,
category,
precondition: ContextKeyExpr.deserialize(enablement),
icon: absoluteIcon
});
_commandRegistrations.add(registration);
}
// remove all previous command registrations
_commandRegistrations.clear();
const newCommands: ICommandAction[] = [];
for (const extension of extensions) {
const { value } = extension;
if (Array.isArray(value)) {
for (const command of value) {
handleCommand(command, extension);
handleCommand(command, extension, newCommands);
}
} else {
handleCommand(value, extension);
handleCommand(value, extension, newCommands);
}
}
_commandRegistrations.add(MenuRegistry.addCommands(newCommands));
});
const _menuRegistrations = new DisposableStore();
@@ -446,6 +447,8 @@ ExtensionsRegistry.registerExtensionPoint<{ [loc: string]: schema.IUserFriendlyM
// remove all previous menu registrations
_menuRegistrations.clear();
const items: { id: MenuId, item: IMenuItem }[] = [];
for (let extension of extensions) {
const { value, collector } = extension;
@@ -467,7 +470,7 @@ ExtensionsRegistry.registerExtensionPoint<{ [loc: string]: schema.IUserFriendlyM
for (let item of entry.value) {
let command = MenuRegistry.getCommand(item.command);
let alt = item.alt && MenuRegistry.getCommand(item.alt);
let alt = item.alt && MenuRegistry.getCommand(item.alt) || undefined;
if (!command) {
collector.error(localize('missing.command', "Menu item references a command `{0}` which is not defined in the 'commands' section.", item.command));
@@ -492,15 +495,19 @@ ExtensionsRegistry.registerExtensionPoint<{ [loc: string]: schema.IUserFriendlyM
}
}
const registration = MenuRegistry.appendMenuItem(menu, {
command,
alt,
group,
order,
when: ContextKeyExpr.deserialize(item.when)
} as IMenuItem);
_menuRegistrations.add(registration);
items.push({
id: menu,
item: {
command,
alt,
group,
order,
when: ContextKeyExpr.deserialize(item.when)
}
});
}
});
}
_menuRegistrations.add(MenuRegistry.appendMenuItems(items));
});
@@ -6,7 +6,6 @@
import { createApiFactoryAndRegisterActors } from 'sql/workbench/api/common/sqlExtHost.api.impl'; // {{SQL CARBON EDIT}} replace with ours
import { ExtensionActivationTimesBuilder } from 'vs/workbench/api/common/extHostExtensionActivator';
import { AbstractExtHostExtensionService } from 'vs/workbench/api/common/extHostExtensionService';
import { endsWith } from 'vs/base/common/strings';
import { URI } from 'vs/base/common/uri';
import { RequireInterceptor } from 'vs/workbench/api/common/extHostRequireInterceptor';
@@ -79,5 +78,5 @@ export class ExtHostExtensionService extends AbstractExtHostExtensionService {
}
function ensureSuffix(path: string, suffix: string): string {
return endsWith(path, suffix) ? path : path + suffix;
return path.endsWith(suffix) ? path : path + suffix;
}
@@ -487,7 +487,7 @@ export class ResetViewLocationsAction extends Action {
}
async run(): Promise<void> {
this.viewDescriptorService.getViewContainers().forEach(viewContainer => {
this.viewDescriptorService.viewContainers.forEach(viewContainer => {
const viewContainerModel = this.viewDescriptorService.getViewContainerModel(viewContainer);
viewContainerModel.allViewDescriptors.forEach(viewDescriptor => {
@@ -596,7 +596,7 @@ export class MoveFocusedViewAction extends Action {
});
}
const pinnedViewlets = this.activityBarService.getPinnedViewletIds();
const pinnedViewlets = this.activityBarService.getPinnedViewContainerIds();
items.push(...pinnedViewlets
.filter(viewletId => {
if (viewletId === this.viewDescriptorService.getViewContainerByViewId(focusedViewId)!.id) {
@@ -7,7 +7,6 @@ import * as nls from 'vs/nls';
import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
import { IWorkspaceEditingService } from 'vs/workbench/services/workspaces/common/workspaceEditing';
import * as resources from 'vs/base/common/resources';
import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet';
import { CancellationToken } from 'vs/base/common/cancellation';
import { mnemonicButtonLabel } from 'vs/base/common/labels';
import { CommandsRegistry } from 'vs/platform/commands/common/commands';
@@ -19,6 +18,7 @@ import { getIconClasses } from 'vs/editor/common/services/getIconClasses';
import { IModelService } from 'vs/editor/common/services/modelService';
import { IModeService } from 'vs/editor/common/services/modeService';
import { IFileDialogService } from 'vs/platform/dialogs/common/dialogs';
import { IViewDescriptorService, IViewsService, ViewContainerLocation } from 'vs/workbench/common/views';
export const ADD_ROOT_FOLDER_COMMAND_ID = 'addRootFolder';
export const ADD_ROOT_FOLDER_LABEL = nls.localize('addFolderToWorkspace', "Add Folder to Workspace...");
@@ -55,7 +55,8 @@ CommandsRegistry.registerCommand({
CommandsRegistry.registerCommand({
id: ADD_ROOT_FOLDER_COMMAND_ID,
handler: async (accessor) => {
const viewletService = accessor.get(IViewletService);
const viewDescriptorService = accessor.get(IViewDescriptorService);
const viewsService = accessor.get(IViewsService);
const workspaceEditingService = accessor.get(IWorkspaceEditingService);
const dialogsService = accessor.get(IFileDialogService);
const folders = await dialogsService.showOpenDialog({
@@ -71,7 +72,7 @@ CommandsRegistry.registerCommand({
}
await workspaceEditingService.addFolders(folders.map(folder => ({ uri: resources.removeTrailingPathSeparator(folder) })));
await viewletService.openViewlet(viewletService.getDefaultViewletId(), true);
await viewsService.openViewContainer(viewDescriptorService.getDefaultViewContainer(ViewContainerLocation.Sidebar)!.id, true);
}
});
+2 -3
View File
@@ -15,7 +15,6 @@ import { trackFocus, Dimension } from 'vs/base/browser/dom';
import { IStorageService } from 'vs/platform/storage/common/storage';
import { Disposable } from 'vs/base/common/lifecycle';
import { assertIsDefined } from 'vs/base/common/types';
import { find } from 'vs/base/common/arrays';
/**
* Composites are layed out in the sidebar and panel part of the workbench. At a time only one composite
@@ -256,7 +255,7 @@ export abstract class CompositeRegistry<T extends Composite> extends Disposable
private readonly _onDidDeregister = this._register(new Emitter<CompositeDescriptor<T>>());
readonly onDidDeregister = this._onDidDeregister.event;
private composites: CompositeDescriptor<T>[] = [];
private readonly composites: CompositeDescriptor<T>[] = [];
protected registerComposite(descriptor: CompositeDescriptor<T>): void {
if (this.compositeById(descriptor.id)) {
@@ -286,6 +285,6 @@ export abstract class CompositeRegistry<T extends Composite> extends Disposable
}
private compositeById(id: string): CompositeDescriptor<T> | undefined {
return find(this.composites, composite => composite.id === id);
return this.composites.find(composite => composite.id === id);
}
}
+2 -2
View File
@@ -8,7 +8,7 @@ import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors';
import { Registry } from 'vs/platform/registry/common/platform';
import { BaseEditor } from 'vs/workbench/browser/parts/editor/baseEditor';
import { IConstructorSignature0, IInstantiationService, BrandedService } from 'vs/platform/instantiation/common/instantiation';
import { find, insert } from 'vs/base/common/arrays';
import { insert } from 'vs/base/common/arrays';
import { IDisposable, toDisposable } from 'vs/base/common/lifecycle';
export interface IEditorDescriptor {
@@ -154,7 +154,7 @@ class EditorRegistry implements IEditorRegistry {
}
getEditorById(editorId: string): EditorDescriptor | undefined {
return find(this.editors, editor => editor.getId() === editorId);
return this.editors.find(editor => editor.getId() === editorId);
}
getEditors(): readonly EditorDescriptor[] {
+8 -5
View File
@@ -43,6 +43,7 @@ import { WINDOW_ACTIVE_BORDER, WINDOW_INACTIVE_BORDER } from 'vs/workbench/commo
import { LineNumbersType } from 'vs/editor/common/config/editorOptions';
import { ActivitybarPart } from 'vs/workbench/browser/parts/activitybar/activitybarPart';
import { URI } from 'vs/base/common/uri';
import { IViewDescriptorService, ViewContainerLocation } from 'vs/workbench/common/views';
export enum Settings {
ACTIVITYBAR_VISIBLE = 'workbench.activityBar.visible',
@@ -171,6 +172,7 @@ export abstract class Layout extends Disposable implements IWorkbenchLayoutServi
private panelService!: IPanelService;
private titleService!: ITitleService;
private viewletService!: IViewletService;
private viewDescriptorService!: IViewDescriptorService;
private contextService!: IWorkspaceContextService;
private backupFileService!: IBackupFileService;
private notificationService!: INotificationService;
@@ -255,6 +257,7 @@ export abstract class Layout extends Disposable implements IWorkbenchLayoutServi
this.editorGroupService = accessor.get(IEditorGroupsService);
this.panelService = accessor.get(IPanelService);
this.viewletService = accessor.get(IViewletService);
this.viewDescriptorService = accessor.get(IViewDescriptorService);
this.titleService = accessor.get(ITitleService);
this.notificationService = accessor.get(INotificationService);
accessor.get(IStatusbarService); // not used, but called to ensure instantiated
@@ -489,11 +492,11 @@ export abstract class Layout extends Disposable implements IWorkbenchLayoutServi
if (!this.state.sideBar.hidden) {
// Only restore last viewlet if window was reloaded or we are in development mode
let viewletToRestore: string;
let viewletToRestore: string | undefined;
if (!this.environmentService.isBuilt || lifecycleService.startupKind === StartupKind.ReloadedWindow || isWeb) {
viewletToRestore = this.storageService.get(SidebarPart.activeViewletSettingsKey, StorageScope.WORKSPACE, this.viewletService.getDefaultViewletId());
viewletToRestore = this.storageService.get(SidebarPart.activeViewletSettingsKey, StorageScope.WORKSPACE, this.viewDescriptorService.getDefaultViewContainer(ViewContainerLocation.Sidebar)?.id);
} else {
viewletToRestore = this.viewletService.getDefaultViewletId();
viewletToRestore = this.viewDescriptorService.getDefaultViewContainer(ViewContainerLocation.Sidebar)?.id;
}
if (viewletToRestore) {
@@ -639,7 +642,7 @@ export abstract class Layout extends Disposable implements IWorkbenchLayoutServi
}
if (sidebarState.length) {
storageService.store(ActivitybarPart.PINNED_VIEWLETS, JSON.stringify(sidebarState), StorageScope.GLOBAL);
storageService.store(ActivitybarPart.PINNED_VIEW_CONTAINERS, JSON.stringify(sidebarState), StorageScope.GLOBAL);
}
}
}
@@ -1344,7 +1347,7 @@ export abstract class Layout extends Disposable implements IWorkbenchLayoutServi
if (viewletToOpen) {
const viewlet = this.viewletService.openViewlet(viewletToOpen, true);
if (!viewlet) {
this.viewletService.openViewlet(this.viewletService.getDefaultViewletId(), true);
this.viewletService.openViewlet(this.viewDescriptorService.getDefaultViewContainer(ViewContainerLocation.Sidebar)?.id, true);
}
}
}
-1
View File
@@ -19,7 +19,6 @@
width: 100%;
height: 100%;
backdrop-filter: brightness(97%) blur(2px);
pointer-events: none;
visibility: hidden;
opacity: 0;
transition: opacity .5s, visibility .5s;
@@ -11,7 +11,6 @@ import { EventType as TouchEventType, GestureEvent } from 'vs/base/browser/touch
import { Action, IAction } from 'vs/base/common/actions';
import { KeyCode } from 'vs/base/common/keyCodes';
import { dispose } from 'vs/base/common/lifecycle';
import { URI } from 'vs/base/common/uri';
import { SyncActionDescriptor, IMenuService, MenuId } from 'vs/platform/actions/common/actions';
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
import { Registry } from 'vs/platform/registry/common/platform';
@@ -19,7 +18,6 @@ import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { activeContrastBorder, focusBorder } from 'vs/platform/theme/common/colorRegistry';
import { ICssStyleCollector, IColorTheme, IThemeService, registerThemingParticipant } from 'vs/platform/theme/common/themeService';
import { ActivityAction, ActivityActionViewItem, ICompositeBar, ICompositeBarColors, ToggleCompositePinnedAction } from 'vs/workbench/browser/parts/compositeBarActions';
import { ViewletDescriptor } from 'vs/workbench/browser/viewlet';
import { Extensions as ActionExtensions, IWorkbenchActionRegistry } from 'vs/workbench/common/actions';
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_BACKGROUND } from 'vs/workbench/common/theme';
@@ -30,9 +28,8 @@ import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { createAndFillInActionBarActions } from 'vs/platform/actions/browser/menuEntryActionViewItem';
import { ICommandService } from 'vs/platform/commands/common/commands';
import { Codicon } from 'vs/base/common/codicons';
import { isString } from 'vs/base/common/types';
export class ViewletActivityAction extends ActivityAction {
export class ViewContainerActivityAction extends ActivityAction {
private static readonly preventDoubleClickDelay = 300;
@@ -48,7 +45,6 @@ export class ViewletActivityAction extends ActivityAction {
@IWorkbenchLayoutService layoutService: IWorkbenchLayoutService,
@ITelemetryService telemetryService: ITelemetryService
) {
ViewletActivityAction.generateIconCSS(activity);
super(activity);
this.lastRun = 0;
@@ -57,23 +53,7 @@ export class ViewletActivityAction extends ActivityAction {
this.telemetryService = telemetryService;
}
private static generateIconCSS(activity: IActivity): void {
if (activity.iconUrl) {
activity.cssClass = activity.cssClass || `activity-${activity.id.replace(/\./g, '-')}`;
const iconClass = `.monaco-workbench .activitybar .monaco-action-bar .action-label.${activity.cssClass}`;
DOM.createCSSRule(iconClass, `
mask: ${DOM.asCSSUrl(activity.iconUrl)} no-repeat 50% 50%;
mask-size: 24px;
-webkit-mask: ${DOM.asCSSUrl(activity.iconUrl)} no-repeat 50% 50%;
-webkit-mask-size: 24px;
`);
}
}
setActivity(activity: IActivity): void {
if (activity.iconUrl && this.activity.cssClass !== activity.cssClass) {
ViewletActivityAction.generateIconCSS(activity);
}
updateActivity(activity: IActivity): void {
this.activity = activity;
}
@@ -84,7 +64,7 @@ export class ViewletActivityAction extends ActivityAction {
// prevent accident trigger on a doubleclick (to help nervous people)
const now = Date.now();
if (now > this.lastRun /* https://github.com/Microsoft/vscode/issues/25830 */ && now - this.lastRun < ViewletActivityAction.preventDoubleClickDelay) {
if (now > this.lastRun /* https://github.com/Microsoft/vscode/issues/25830 */ && now - this.lastRun < ViewContainerActivityAction.preventDoubleClickDelay) {
return;
}
this.lastRun = now;
@@ -113,30 +93,6 @@ export class ViewletActivityAction extends ActivityAction {
}
}
export class ToggleViewletAction extends Action {
constructor(
private _viewlet: ViewletDescriptor,
@IWorkbenchLayoutService private readonly layoutService: IWorkbenchLayoutService,
@IViewletService private readonly viewletService: IViewletService
) {
super(_viewlet.id, _viewlet.name);
}
async run(): Promise<void> {
const sideBarVisible = this.layoutService.isVisible(Parts.SIDEBAR_PART);
const activeViewlet = this.viewletService.getActiveViewlet();
// Hide sidebar if selected viewlet already visible
if (sideBarVisible && activeViewlet?.getId() === this._viewlet.id) {
this.layoutService.setSideBarHidden(true);
return;
}
await this.viewletService.openViewlet(this._viewlet.id, true);
}
}
export class AccountsActionViewItem extends ActivityActionViewItem {
constructor(
action: ActivityAction,
@@ -248,23 +204,7 @@ export class GlobalActivityActionViewItem extends ActivityActionViewItem {
}
}
export class PlaceHolderViewletActivityAction extends ViewletActivityAction {
constructor(
id: string,
icon: URI | string | undefined,
@IViewletService viewletService: IViewletService,
@IWorkbenchLayoutService layoutService: IWorkbenchLayoutService,
@ITelemetryService telemetryService: ITelemetryService
) {
super({
id,
name: id,
iconUrl: URI.isUri(icon) ? icon : undefined,
cssClass: isString(icon) ? icon : undefined
}, viewletService, layoutService, telemetryService);
}
}
export class PlaceHolderViewContainerActivityAction extends ViewContainerActivityAction { }
export class PlaceHolderToggleCompositePinnedAction extends ToggleCompositePinnedAction {
@@ -289,16 +229,16 @@ class SwitchSideBarViewAction extends Action {
}
async run(offset: number): Promise<void> {
const pinnedViewletIds = this.activityBarService.getPinnedViewletIds();
const visibleViewletIds = this.activityBarService.getVisibleViewContainerIds();
const activeViewlet = this.viewletService.getActiveViewlet();
if (!activeViewlet) {
return;
}
let targetViewletId: string | undefined;
for (let i = 0; i < pinnedViewletIds.length; i++) {
if (pinnedViewletIds[i] === activeViewlet.getId()) {
targetViewletId = pinnedViewletIds[(i + pinnedViewletIds.length + offset) % pinnedViewletIds.length];
for (let i = 0; i < visibleViewletIds.length; i++) {
if (visibleViewletIds[i] === activeViewlet.getId()) {
targetViewletId = visibleViewletIds[(i + visibleViewletIds.length + offset) % visibleViewletIds.length];
break;
}
}
@@ -8,8 +8,7 @@ import * as nls from 'vs/nls';
import { ActionsOrientation, ActionBar } from 'vs/base/browser/ui/actionbar/actionbar';
import { GLOBAL_ACTIVITY_ID, IActivity } from 'vs/workbench/common/activity';
import { Part } from 'vs/workbench/browser/part';
import { GlobalActivityActionViewItem, ViewletActivityAction, ToggleViewletAction, PlaceHolderToggleCompositePinnedAction, PlaceHolderViewletActivityAction, AccountsActionViewItem, HomeAction } from 'vs/workbench/browser/parts/activitybar/activitybarActions';
import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet';
import { GlobalActivityActionViewItem, ViewContainerActivityAction, PlaceHolderToggleCompositePinnedAction, PlaceHolderViewContainerActivityAction, AccountsActionViewItem, HomeAction } from 'vs/workbench/browser/parts/activitybar/activitybarActions';
import { IBadge, NumberBadge } from 'vs/workbench/services/activity/common/activity';
import { IWorkbenchLayoutService, Parts, Position as SideBarPosition } from 'vs/workbench/services/layout/browser/layoutService';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
@@ -19,15 +18,13 @@ import { IThemeService, IColorTheme } from 'vs/platform/theme/common/themeServic
import { ACTIVITY_BAR_BACKGROUND, ACTIVITY_BAR_BORDER, ACTIVITY_BAR_FOREGROUND, ACTIVITY_BAR_ACTIVE_BORDER, ACTIVITY_BAR_BADGE_BACKGROUND, ACTIVITY_BAR_BADGE_FOREGROUND, ACTIVITY_BAR_DRAG_AND_DROP_BACKGROUND, ACTIVITY_BAR_INACTIVE_FOREGROUND, ACTIVITY_BAR_ACTIVE_BACKGROUND } from 'vs/workbench/common/theme';
import { contrastBorder } from 'vs/platform/theme/common/colorRegistry';
import { CompositeBar, ICompositeBarItem, CompositeDragAndDrop } from 'vs/workbench/browser/parts/compositeBar';
import { Dimension, addClass, removeNode } from 'vs/base/browser/dom';
import { Dimension, addClass, removeNode, createCSSRule, asCSSUrl } from 'vs/base/browser/dom';
import { IStorageService, StorageScope, IWorkspaceStorageChangeEvent } from 'vs/platform/storage/common/storage';
import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions';
import { URI, UriComponents } from 'vs/base/common/uri';
import { ToggleCompositePinnedAction, ICompositeBarColors, ActivityAction, ICompositeActivity } from 'vs/workbench/browser/parts/compositeBarActions';
import { ViewletDescriptor } from 'vs/workbench/browser/viewlet';
import { IViewDescriptorService, ViewContainer, TEST_VIEW_CONTAINER_ID, IViewContainerModel, ViewContainerLocation } from 'vs/workbench/common/views';
import { IViewDescriptorService, ViewContainer, TEST_VIEW_CONTAINER_ID, IViewContainerModel, ViewContainerLocation, IViewsService } from 'vs/workbench/common/views';
import { IContextKeyService, ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
import { IViewlet } from 'vs/workbench/common/viewlet';
import { isUndefinedOrNull, assertIsDefined, isString } from 'vs/base/common/types';
import { IActivityBarService } from 'vs/workbench/services/activityBar/browser/activityBarService';
import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
@@ -42,8 +39,10 @@ import { getUserDataSyncStore } from 'vs/platform/userDataSync/common/userDataSy
import { IProductService } from 'vs/platform/product/common/productService';
import { Before2D } from 'vs/workbench/browser/dnd';
import { Codicon, iconRegistry } from 'vs/base/common/codicons';
import { Action } from 'vs/base/common/actions';
import { Event } from 'vs/base/common/event';
interface IPlaceholderViewlet {
interface IPlaceholderViewContainer {
id: string;
name?: string;
iconUrl?: UriComponents;
@@ -51,14 +50,14 @@ interface IPlaceholderViewlet {
views?: { when?: string }[];
}
interface IPinnedViewlet {
interface IPinnedViewContainer {
id: string;
pinned: boolean;
order?: number;
visible: boolean;
}
interface ICachedViewlet {
interface ICachedViewContainer {
id: string;
name?: string;
icon?: URI | string;
@@ -73,8 +72,8 @@ export class ActivitybarPart extends Part implements IActivityBarService {
_serviceBrand: undefined;
private static readonly ACTION_HEIGHT = 48;
static readonly PINNED_VIEWLETS = 'workbench.activity.pinnedViewlets2';
private static readonly PLACEHOLDER_VIEWLETS = 'workbench.activity.placeholderViewlets';
static readonly PINNED_VIEW_CONTAINERS = 'workbench.activity.pinnedViewlets2';
private static readonly PLACEHOLDER_VIEW_CONTAINERS = 'workbench.activity.placeholderViewlets';
//#region IView
@@ -99,18 +98,20 @@ export class ActivitybarPart extends Part implements IActivityBarService {
private globalActivityActionBar: ActionBar | undefined;
private readonly globalActivity: ICompositeActivity[] = [];
private readonly cachedViewlets: ICachedViewlet[] = [];
private readonly compositeActions = new Map<string, { activityAction: ViewletActivityAction, pinnedAction: ToggleCompositePinnedAction }>();
private readonly viewletDisposables = new Map<string, IDisposable>();
private readonly cachedViewContainers: ICachedViewContainer[] = [];
private readonly compositeActions = new Map<string, { activityAction: ViewContainerActivityAction, pinnedAction: ToggleCompositePinnedAction }>();
private readonly viewContainerDisposables = new Map<string, IDisposable>();
private readonly location = ViewContainerLocation.Sidebar;
constructor(
@IViewletService private readonly viewletService: IViewletService,
@IInstantiationService private readonly instantiationService: IInstantiationService,
@IWorkbenchLayoutService layoutService: IWorkbenchLayoutService,
@IThemeService themeService: IThemeService,
@IStorageService private readonly storageService: IStorageService,
@IExtensionService private readonly extensionService: IExtensionService,
@IViewDescriptorService private readonly viewDescriptorService: IViewDescriptorService,
@IViewsService private readonly viewsService: IViewsService,
@IContextKeyService private readonly contextKeyService: IContextKeyService,
@IConfigurationService private readonly configurationService: IConfigurationService,
@IWorkbenchEnvironmentService private readonly environmentService: IWorkbenchEnvironmentService,
@@ -119,27 +120,27 @@ export class ActivitybarPart extends Part implements IActivityBarService {
) {
super(Parts.ACTIVITYBAR_PART, { hasTitle: false }, themeService, storageService, layoutService);
storageKeysSyncRegistryService.registerStorageKey({ key: ActivitybarPart.PINNED_VIEWLETS, version: 1 });
this.migrateFromOldCachedViewletsValue();
storageKeysSyncRegistryService.registerStorageKey({ key: ActivitybarPart.PINNED_VIEW_CONTAINERS, version: 1 });
this.migrateFromOldCachedViewContainersValue();
this.cachedViewlets = this.getCachedViewlets();
for (const cachedViewlet of this.cachedViewlets) {
this.cachedViewContainers = this.getCachedViewContainers();
for (const cachedViewContainer of this.cachedViewContainers) {
if (environmentService.configuration.remoteAuthority // In remote window, hide activity bar entries until registered.
|| this.shouldBeHidden(cachedViewlet.id, cachedViewlet)
|| this.shouldBeHidden(cachedViewContainer.id, cachedViewContainer)
) {
cachedViewlet.visible = false;
cachedViewContainer.visible = false;
}
}
const cachedItems = this.cachedViewlets
const cachedItems = this.cachedViewContainers
.map(v => ({ id: v.id, name: v.name, visible: v.visible, order: v.order, pinned: v.pinned }));
this.compositeBar = this._register(this.instantiationService.createInstance(CompositeBar, cachedItems, {
icon: true,
orientation: ActionsOrientation.VERTICAL,
openComposite: (compositeId: string) => this.viewletService.openViewlet(compositeId, true),
openComposite: (compositeId: string) => this.viewsService.openViewContainer(compositeId, true),
getActivityAction: (compositeId: string) => this.getCompositeActions(compositeId).activityAction,
getCompositePinnedAction: (compositeId: string) => this.getCompositeActions(compositeId).pinnedAction,
getOnCompositeClickAction: (compositeId: string) => this.instantiationService.createInstance(ToggleViewletAction, assertIsDefined(this.viewletService.getViewlet(compositeId))),
getOnCompositeClickAction: (compositeId: string) => new Action(compositeId, '', '', true, () => this.viewsService.isViewContainerVisible(compositeId) ? Promise.resolve(this.viewsService.closeViewContainer(compositeId)) : this.viewsService.openViewContainer(compositeId)),
getContextMenuActions: () => {
const menuBarVisibility = getMenuBarVisibility(this.configurationService, this.environmentService);
const actions = [];
@@ -152,10 +153,10 @@ export class ActivitybarPart extends Part implements IActivityBarService {
return actions;
},
getContextMenuActionsForComposite: () => [],
getDefaultCompositeId: () => this.viewletService.getDefaultViewletId(),
getDefaultCompositeId: () => this.viewDescriptorService.getDefaultViewContainer(this.location)!.id,
hidePart: () => this.layoutService.setSideBarHidden(true),
dndHandler: new CompositeDragAndDrop(this.viewDescriptorService, ViewContainerLocation.Sidebar,
(id: string, focus?: boolean) => this.viewletService.openViewlet(id, focus),
(id: string, focus?: boolean) => this.viewsService.openViewContainer(id, focus),
(from: string, to: string, before?: Before2D) => this.compositeBar.move(from, to, before?.verticallyBefore)
),
compositeSize: 52,
@@ -163,28 +164,25 @@ export class ActivitybarPart extends Part implements IActivityBarService {
overflowActionSize: ActivitybarPart.ACTION_HEIGHT
}));
this.onDidRegisterViewContainers(this.getViewContainers());
this.registerListeners();
this.onDidRegisterViewlets(viewletService.getViewlets());
}
private registerListeners(): void {
// Viewlet registration
this._register(this.viewletService.onDidViewletRegister(viewlet => this.onDidRegisterViewlets([viewlet])));
this._register(this.viewletService.onDidViewletDeregister(({ id }) => this.onDidDeregisterViewlet(id)));
// View Container Changes
this._register(this.viewDescriptorService.onDidChangeViewContainers(({ added, removed }) => this.onDidChangeViewContainers(added, removed)));
this._register(this.viewDescriptorService.onDidChangeContainerLocation(({ viewContainer, from, to }) => this.onDidChangeViewContainerLocation(viewContainer, from, to)));
// Activate viewlet action on opening of a viewlet
this._register(this.viewletService.onDidViewletOpen(viewlet => this.onDidViewletOpen(viewlet)));
// Deactivate viewlet action on close
this._register(this.viewletService.onDidViewletClose(viewlet => this.compositeBar.deactivateComposite(viewlet.getId())));
// View Container Visibility Changes
this._register(Event.filter(this.viewsService.onDidChangeViewContainerVisibility, e => e.location === this.location)(({ id, visible }) => this.onDidChangeViewContainerVisibility(id, visible)));
// Extension registration
let disposables = this._register(new DisposableStore());
this._register(this.extensionService.onDidRegisterExtensions(() => {
disposables.clear();
this.onDidRegisterExtensions();
this.compositeBar.onDidChange(() => this.saveCachedViewlets(), this, disposables);
this.compositeBar.onDidChange(() => this.saveCachedViewContainers(), this, disposables);
this.storageService.onDidChangeStorage(e => this.onDidStorageChange(e), this, disposables);
}));
@@ -200,39 +198,57 @@ export class ActivitybarPart extends Part implements IActivityBarService {
}));
}
private onDidRegisterExtensions(): void {
this.removeNotExistingComposites();
this.saveCachedViewlets();
private onDidChangeViewContainers(added: ReadonlyArray<{ container: ViewContainer, location: ViewContainerLocation }>, removed: ReadonlyArray<{ container: ViewContainer, location: ViewContainerLocation }>) {
removed.filter(({ location }) => location === ViewContainerLocation.Sidebar).forEach(({ container }) => this.onDidDeregisterViewContainer(container));
this.onDidRegisterViewContainers(added.filter(({ location }) => location === ViewContainerLocation.Sidebar).map(({ container }) => container));
}
private onDidViewletOpen(viewlet: IViewlet): void {
// Update the composite bar by adding
const foundViewlet = this.viewletService.getViewlet(viewlet.getId());
if (foundViewlet) {
this.compositeBar.addComposite(foundViewlet);
private onDidChangeViewContainerLocation(container: ViewContainer, from: ViewContainerLocation, to: ViewContainerLocation) {
if (from === this.location) {
this.onDidDeregisterViewContainer(container);
}
if (to === this.location) {
this.onDidRegisterViewContainers([container]);
}
}
this.compositeBar.activateComposite(viewlet.getId());
private onDidChangeViewContainerVisibility(id: string, visible: boolean) {
if (visible) {
// Activate view container action on opening of a view container
this.onDidViewContainerVisible(id);
} else {
// Deactivate view container action on close
this.compositeBar.deactivateComposite(id);
}
}
const viewletDescriptor = this.viewletService.getViewlet(viewlet.getId());
if (viewletDescriptor) {
const viewContainer = this.getViewContainer(viewletDescriptor.id);
if (viewContainer?.hideIfEmpty) {
private onDidRegisterExtensions(): void {
this.removeNotExistingComposites();
this.saveCachedViewContainers();
}
private onDidViewContainerVisible(id: string): void {
const viewContainer = this.getViewContainer(id);
if (viewContainer) {
// Update the composite bar by adding
this.compositeBar.addComposite(viewContainer);
this.compositeBar.activateComposite(viewContainer.id);
if (viewContainer.hideIfEmpty) {
const viewContainerModel = this.viewDescriptorService.getViewContainerModel(viewContainer);
if (viewContainerModel.activeViewDescriptors.length === 0) {
this.hideComposite(viewletDescriptor.id); // Update the composite bar by hiding
this.hideComposite(viewContainer.id); // Update the composite bar by hiding
}
}
}
}
showActivity(viewletOrActionId: string, badge: IBadge, clazz?: string, priority?: number): IDisposable {
if (this.viewletService.getViewlet(viewletOrActionId)) {
return this.compositeBar.showActivity(viewletOrActionId, badge, clazz, priority);
showActivity(viewContainerOrActionId: string, badge: IBadge, clazz?: string, priority?: number): IDisposable {
if (this.getViewContainer(viewContainerOrActionId)) {
return this.compositeBar.showActivity(viewContainerOrActionId, badge, clazz, priority);
}
if (viewletOrActionId === GLOBAL_ACTIVITY_ID) {
if (viewContainerOrActionId === GLOBAL_ACTIVITY_ID) {
return this.showGlobalActivity(badge, clazz, priority);
}
@@ -342,7 +358,7 @@ export class ActivitybarPart extends Part implements IActivityBarService {
this.installMenubar();
}
// Viewlets action bar
// View Containers action bar
this.compositeBar.create(this.content);
// Global action bar
@@ -444,19 +460,20 @@ export class ActivitybarPart extends Part implements IActivityBarService {
this.globalActivityActionBar.push(this.globalActivityAction);
}
private getCompositeActions(compositeId: string): { activityAction: ViewletActivityAction, pinnedAction: ToggleCompositePinnedAction } {
private getCompositeActions(compositeId: string): { activityAction: ViewContainerActivityAction, pinnedAction: ToggleCompositePinnedAction } {
let compositeActions = this.compositeActions.get(compositeId);
if (!compositeActions) {
const viewlet = this.viewletService.getViewlet(compositeId);
if (viewlet) {
const viewContainer = this.getViewContainer(compositeId);
if (viewContainer) {
const viewContainerModel = this.viewDescriptorService.getViewContainerModel(viewContainer);
compositeActions = {
activityAction: this.instantiationService.createInstance(ViewletActivityAction, viewlet),
pinnedAction: new ToggleCompositePinnedAction(viewlet, this.compositeBar)
activityAction: this.instantiationService.createInstance(ViewContainerActivityAction, this.toActivity(viewContainer, viewContainerModel)),
pinnedAction: new ToggleCompositePinnedAction(viewContainer, this.compositeBar)
};
} else {
const cachedComposite = this.cachedViewlets.filter(c => c.id === compositeId)[0];
const cachedComposite = this.cachedViewContainers.filter(c => c.id === compositeId)[0];
compositeActions = {
activityAction: this.instantiationService.createInstance(PlaceHolderViewletActivityAction, compositeId, cachedComposite?.icon),
activityAction: this.instantiationService.createInstance(PlaceHolderViewContainerActivityAction, ActivitybarPart.toActivity(compositeId, compositeId, cachedComposite?.icon, undefined)),
pinnedAction: new PlaceHolderToggleCompositePinnedAction(compositeId, this.compositeBar)
};
}
@@ -467,28 +484,27 @@ export class ActivitybarPart extends Part implements IActivityBarService {
return compositeActions;
}
private onDidRegisterViewlets(viewlets: ViewletDescriptor[]): void {
for (const viewlet of viewlets) {
const cachedViewlet = this.cachedViewlets.filter(({ id }) => id === viewlet.id)[0];
const activeViewlet = this.viewletService.getActiveViewlet();
const isActive = activeViewlet?.getId() === viewlet.id;
private onDidRegisterViewContainers(viewContainers: ReadonlyArray<ViewContainer>): void {
for (const viewContainer of viewContainers) {
const cachedViewContainer = this.cachedViewContainers.filter(({ id }) => id === viewContainer.id)[0];
const visibleViewContainer = this.viewsService.getVisibleViewContainer(this.location);
const isActive = visibleViewContainer?.id === viewContainer.id;
if (isActive || !this.shouldBeHidden(viewlet.id, cachedViewlet)) {
this.compositeBar.addComposite(viewlet);
if (isActive || !this.shouldBeHidden(viewContainer.id, cachedViewContainer)) {
this.compositeBar.addComposite(viewContainer);
// Pin it by default if it is new
if (!cachedViewlet) {
this.compositeBar.pin(viewlet.id);
if (!cachedViewContainer) {
this.compositeBar.pin(viewContainer.id);
}
if (isActive) {
this.compositeBar.activateComposite(viewlet.id);
this.compositeBar.activateComposite(viewContainer.id);
}
}
}
for (const viewlet of viewlets) {
const viewContainer = this.getViewContainer(viewlet.id)!;
for (const viewContainer of viewContainers) {
const viewContainerModel = this.viewDescriptorService.getViewContainerModel(viewContainer);
this.updateActivity(viewContainer, viewContainerModel);
this.onDidChangeActiveViews(viewContainer, viewContainerModel);
@@ -497,38 +513,53 @@ export class ActivitybarPart extends Part implements IActivityBarService {
disposables.add(viewContainerModel.onDidChangeContainerInfo(() => this.updateActivity(viewContainer, viewContainerModel)));
disposables.add(viewContainerModel.onDidChangeActiveViewDescriptors(() => this.onDidChangeActiveViews(viewContainer, viewContainerModel)));
this.viewletDisposables.set(viewlet.id, disposables);
this.viewContainerDisposables.set(viewContainer.id, disposables);
}
}
private onDidDeregisterViewlet(viewletId: string): void {
const disposable = this.viewletDisposables.get(viewletId);
private onDidDeregisterViewContainer(viewContainer: ViewContainer): void {
const disposable = this.viewContainerDisposables.get(viewContainer.id);
if (disposable) {
disposable.dispose();
}
this.viewletDisposables.delete(viewletId);
this.hideComposite(viewletId);
this.viewContainerDisposables.delete(viewContainer.id);
this.hideComposite(viewContainer.id);
}
private updateActivity(viewContainer: ViewContainer, viewContainerModel: IViewContainerModel): void {
const activity: IActivity = {
id: viewContainer.id,
name: viewContainerModel.title,
iconUrl: URI.isUri(viewContainerModel.icon) ? viewContainerModel.icon : undefined,
cssClass: isString(viewContainerModel.icon) ? viewContainerModel.icon : undefined,
keybindingId: viewContainer.focusCommand?.id || viewContainer.id
};
const activity: IActivity = this.toActivity(viewContainer, viewContainerModel);
const { activityAction, pinnedAction } = this.getCompositeActions(viewContainer.id);
activityAction.setActivity(activity);
activityAction.updateActivity(activity);
if (pinnedAction instanceof PlaceHolderToggleCompositePinnedAction) {
pinnedAction.setActivity(activity);
}
this.saveCachedViewlets();
this.saveCachedViewContainers();
}
private toActivity({ id, focusCommand }: ViewContainer, { icon, title: name }: IViewContainerModel): IActivity {
return ActivitybarPart.toActivity(id, name, icon, focusCommand?.id || id);
}
private static toActivity(id: string, name: string, icon: URI | string | undefined, keybindingId: string | undefined): IActivity {
let cssClass: string | undefined = undefined;
let iconUrl: URI | undefined = undefined;
if (URI.isUri(icon)) {
iconUrl = icon;
cssClass = `activity-${id.replace(/\./g, '-')}`;
const iconClass = `.monaco-workbench .activitybar .monaco-action-bar .action-label.${cssClass}`;
createCSSRule(iconClass, `
mask: ${asCSSUrl(icon)} no-repeat 50% 50%;
mask-size: 24px;
-webkit-mask: ${asCSSUrl(icon)} no-repeat 50% 50%;
-webkit-mask-size: 24px;
`);
} else if (isString(icon)) {
cssClass = icon;
}
return { id, name, cssClass, iconUrl, keybindingId };
}
private onDidChangeActiveViews(viewContainer: ViewContainer, viewContainerModel: IViewContainerModel): void {
@@ -539,21 +570,21 @@ export class ActivitybarPart extends Part implements IActivityBarService {
}
}
private shouldBeHidden(viewletId: string, cachedViewlet?: ICachedViewlet): boolean {
const viewContainer = this.getViewContainer(viewletId);
private shouldBeHidden(viewContainerId: string, cachedViewContainer?: ICachedViewContainer): boolean {
const viewContainer = this.getViewContainer(viewContainerId);
if (!viewContainer || !viewContainer.hideIfEmpty) {
return false;
}
return cachedViewlet?.views && cachedViewlet.views.length
? cachedViewlet.views.every(({ when }) => !!when && !this.contextKeyService.contextMatchesRules(ContextKeyExpr.deserialize(when)))
: viewletId === TEST_VIEW_CONTAINER_ID /* Hide Test viewlet for the first time or it had no views registered before */;
return cachedViewContainer?.views && cachedViewContainer.views.length
? cachedViewContainer.views.every(({ when }) => !!when && !this.contextKeyService.contextMatchesRules(ContextKeyExpr.deserialize(when)))
: viewContainerId === TEST_VIEW_CONTAINER_ID /* Hide Test view container for the first time or it had no views registered before */;
}
private removeNotExistingComposites(): void {
const viewlets = this.viewletService.getViewlets();
for (const { id } of this.cachedViewlets) {
if (viewlets.every(viewlet => viewlet.id !== id)) {
const viewContainers = this.getViewContainers();
for (const { id } of this.cachedViewContainers) {
if (viewContainers.every(viewContainer => viewContainer.id !== id)) {
this.hideComposite(id);
}
}
@@ -570,15 +601,20 @@ export class ActivitybarPart extends Part implements IActivityBarService {
}
}
getPinnedViewletIds(): string[] {
getPinnedViewContainerIds(): string[] {
const pinnedCompositeIds = this.compositeBar.getPinnedComposites().map(v => v.id);
return this.viewletService.getViewlets()
return this.getViewContainers()
.filter(v => this.compositeBar.isPinned(v.id))
.sort((v1, v2) => pinnedCompositeIds.indexOf(v1.id) - pinnedCompositeIds.indexOf(v2.id))
.map(v => v.id);
}
getVisibleViewContainerIds(): string[] {
return this.compositeBar.getVisibleComposites()
.filter(v => this.viewsService.getVisibleViewContainer(this.location)?.id === v.id || this.compositeBar.isPinned(v.id))
.map(v => v.id);
}
layout(width: number, height: number): void {
if (!this.layoutService.isVisible(Parts.ACTIVITYBAR_PART)) {
return;
@@ -601,27 +637,32 @@ export class ActivitybarPart extends Part implements IActivityBarService {
this.compositeBar.layout(new Dimension(width, availableHeight));
}
private getViewContainer(viewletId: string): ViewContainer | undefined {
return this.viewDescriptorService.getViewContainerById(viewletId) || undefined;
private getViewContainer(id: string): ViewContainer | undefined {
const viewContainer = this.viewDescriptorService.getViewContainerById(id);
return viewContainer && this.viewDescriptorService.getViewContainerLocation(viewContainer) === this.location ? viewContainer : undefined;
}
private getViewContainers(): ReadonlyArray<ViewContainer> {
return this.viewDescriptorService.getViewContainersByLocation(this.location);
}
private onDidStorageChange(e: IWorkspaceStorageChangeEvent): void {
if (e.key === ActivitybarPart.PINNED_VIEWLETS && e.scope === StorageScope.GLOBAL
&& this.pinnedViewletsValue !== this.getStoredPinnedViewletsValue() /* This checks if current window changed the value or not */) {
this._pinnedViewletsValue = undefined;
if (e.key === ActivitybarPart.PINNED_VIEW_CONTAINERS && e.scope === StorageScope.GLOBAL
&& this.pinnedViewContainersValue !== this.getStoredPinnedViewContainersValue() /* This checks if current window changed the value or not */) {
this._pinnedViewContainersValue = undefined;
const newCompositeItems: ICompositeBarItem[] = [];
const compositeItems = this.compositeBar.getCompositeBarItems();
const cachedViewlets = this.getCachedViewlets();
const cachedViewContainers = this.getCachedViewContainers();
for (const cachedViewlet of cachedViewlets) {
for (const cachedViewContainer of cachedViewContainers) {
// Add and update existing items
const existingItem = compositeItems.filter(({ id }) => id === cachedViewlet.id)[0];
const existingItem = compositeItems.filter(({ id }) => id === cachedViewContainer.id)[0];
if (existingItem) {
newCompositeItems.push({
id: existingItem.id,
name: existingItem.name,
order: existingItem.order,
pinned: cachedViewlet.pinned,
pinned: cachedViewContainer.pinned,
visible: existingItem.visible
});
}
@@ -638,8 +679,8 @@ export class ActivitybarPart extends Part implements IActivityBarService {
}
}
private saveCachedViewlets(): void {
const state: ICachedViewlet[] = [];
private saveCachedViewContainers(): void {
const state: ICachedViewContainer[] = [];
const compositeItems = this.compositeBar.getCompositeBarItems();
for (const compositeItem of compositeItems) {
@@ -665,32 +706,32 @@ export class ActivitybarPart extends Part implements IActivityBarService {
}
}
this.storeCachedViewletsState(state);
this.storeCachedViewContainersState(state);
}
private getCachedViewlets(): ICachedViewlet[] {
const cachedViewlets: ICachedViewlet[] = this.getPinnedViewlets();
for (const placeholderViewlet of this.getPlaceholderViewlets()) {
const cachedViewlet = cachedViewlets.filter(cached => cached.id === placeholderViewlet.id)[0];
if (cachedViewlet) {
cachedViewlet.name = placeholderViewlet.name;
cachedViewlet.icon = placeholderViewlet.iconCSS ? placeholderViewlet.iconCSS :
placeholderViewlet.iconUrl ? URI.revive(placeholderViewlet.iconUrl) : undefined;
cachedViewlet.views = placeholderViewlet.views;
private getCachedViewContainers(): ICachedViewContainer[] {
const cachedViewContainers: ICachedViewContainer[] = this.getPinnedViewContainers();
for (const placeholderViewContainer of this.getPlaceholderViewContainers()) {
const cachedViewContainer = cachedViewContainers.filter(cached => cached.id === placeholderViewContainer.id)[0];
if (cachedViewContainer) {
cachedViewContainer.name = placeholderViewContainer.name;
cachedViewContainer.icon = placeholderViewContainer.iconCSS ? placeholderViewContainer.iconCSS :
placeholderViewContainer.iconUrl ? URI.revive(placeholderViewContainer.iconUrl) : undefined;
cachedViewContainer.views = placeholderViewContainer.views;
}
}
return cachedViewlets;
return cachedViewContainers;
}
private storeCachedViewletsState(cachedViewlets: ICachedViewlet[]): void {
this.setPinnedViewlets(cachedViewlets.map(({ id, pinned, visible, order }) => (<IPinnedViewlet>{
private storeCachedViewContainersState(cachedViewContainers: ICachedViewContainer[]): void {
this.setPinnedViewContainers(cachedViewContainers.map(({ id, pinned, visible, order }) => (<IPinnedViewContainer>{
id,
pinned,
visible,
order
})));
this.setPlaceholderViewlets(cachedViewlets.map(({ id, icon, name, views }) => (<IPlaceholderViewlet>{
this.setPlaceholderViewContainers(cachedViewContainers.map(({ id, icon, name, views }) => (<IPlaceholderViewContainer>{
id,
iconUrl: URI.isUri(icon) ? icon : undefined,
iconCSS: isString(icon) ? icon : undefined,
@@ -699,80 +740,80 @@ export class ActivitybarPart extends Part implements IActivityBarService {
})));
}
private getPinnedViewlets(): IPinnedViewlet[] {
return JSON.parse(this.pinnedViewletsValue);
private getPinnedViewContainers(): IPinnedViewContainer[] {
return JSON.parse(this.pinnedViewContainersValue);
}
private setPinnedViewlets(pinnedViewlets: IPinnedViewlet[]): void {
this.pinnedViewletsValue = JSON.stringify(pinnedViewlets);
private setPinnedViewContainers(pinnedViewContainers: IPinnedViewContainer[]): void {
this.pinnedViewContainersValue = JSON.stringify(pinnedViewContainers);
}
private _pinnedViewletsValue: string | undefined;
private get pinnedViewletsValue(): string {
if (!this._pinnedViewletsValue) {
this._pinnedViewletsValue = this.getStoredPinnedViewletsValue();
private _pinnedViewContainersValue: string | undefined;
private get pinnedViewContainersValue(): string {
if (!this._pinnedViewContainersValue) {
this._pinnedViewContainersValue = this.getStoredPinnedViewContainersValue();
}
return this._pinnedViewletsValue;
return this._pinnedViewContainersValue;
}
private set pinnedViewletsValue(pinnedViewletsValue: string) {
if (this.pinnedViewletsValue !== pinnedViewletsValue) {
this._pinnedViewletsValue = pinnedViewletsValue;
this.setStoredPinnedViewletsValue(pinnedViewletsValue);
private set pinnedViewContainersValue(pinnedViewContainersValue: string) {
if (this.pinnedViewContainersValue !== pinnedViewContainersValue) {
this._pinnedViewContainersValue = pinnedViewContainersValue;
this.setStoredPinnedViewContainersValue(pinnedViewContainersValue);
}
}
private getStoredPinnedViewletsValue(): string {
return this.storageService.get(ActivitybarPart.PINNED_VIEWLETS, StorageScope.GLOBAL, '[]');
private getStoredPinnedViewContainersValue(): string {
return this.storageService.get(ActivitybarPart.PINNED_VIEW_CONTAINERS, StorageScope.GLOBAL, '[]');
}
private setStoredPinnedViewletsValue(value: string): void {
this.storageService.store(ActivitybarPart.PINNED_VIEWLETS, value, StorageScope.GLOBAL);
private setStoredPinnedViewContainersValue(value: string): void {
this.storageService.store(ActivitybarPart.PINNED_VIEW_CONTAINERS, value, StorageScope.GLOBAL);
}
private getPlaceholderViewlets(): IPlaceholderViewlet[] {
return JSON.parse(this.placeholderViewletsValue);
private getPlaceholderViewContainers(): IPlaceholderViewContainer[] {
return JSON.parse(this.placeholderViewContainersValue);
}
private setPlaceholderViewlets(placeholderViewlets: IPlaceholderViewlet[]): void {
this.placeholderViewletsValue = JSON.stringify(placeholderViewlets);
private setPlaceholderViewContainers(placeholderViewContainers: IPlaceholderViewContainer[]): void {
this.placeholderViewContainersValue = JSON.stringify(placeholderViewContainers);
}
private _placeholderViewletsValue: string | undefined;
private get placeholderViewletsValue(): string {
if (!this._placeholderViewletsValue) {
this._placeholderViewletsValue = this.getStoredPlaceholderViewletsValue();
private _placeholderViewContainersValue: string | undefined;
private get placeholderViewContainersValue(): string {
if (!this._placeholderViewContainersValue) {
this._placeholderViewContainersValue = this.getStoredPlaceholderViewContainersValue();
}
return this._placeholderViewletsValue;
return this._placeholderViewContainersValue;
}
private set placeholderViewletsValue(placeholderViewletsValue: string) {
if (this.placeholderViewletsValue !== placeholderViewletsValue) {
this._placeholderViewletsValue = placeholderViewletsValue;
this.setStoredPlaceholderViewletsValue(placeholderViewletsValue);
private set placeholderViewContainersValue(placeholderViewContainesValue: string) {
if (this.placeholderViewContainersValue !== placeholderViewContainesValue) {
this._placeholderViewContainersValue = placeholderViewContainesValue;
this.setStoredPlaceholderViewContainersValue(placeholderViewContainesValue);
}
}
private getStoredPlaceholderViewletsValue(): string {
return this.storageService.get(ActivitybarPart.PLACEHOLDER_VIEWLETS, StorageScope.GLOBAL, '[]');
private getStoredPlaceholderViewContainersValue(): string {
return this.storageService.get(ActivitybarPart.PLACEHOLDER_VIEW_CONTAINERS, StorageScope.GLOBAL, '[]');
}
private setStoredPlaceholderViewletsValue(value: string): void {
this.storageService.store(ActivitybarPart.PLACEHOLDER_VIEWLETS, value, StorageScope.GLOBAL);
private setStoredPlaceholderViewContainersValue(value: string): void {
this.storageService.store(ActivitybarPart.PLACEHOLDER_VIEW_CONTAINERS, value, StorageScope.GLOBAL);
}
private migrateFromOldCachedViewletsValue(): void {
private migrateFromOldCachedViewContainersValue(): void {
const value = this.storageService.get('workbench.activity.pinnedViewlets', StorageScope.GLOBAL);
if (value !== undefined) {
const storedStates: Array<string | ICachedViewlet> = JSON.parse(value);
const cachedViewlets = storedStates.map(c => {
const serialized: ICachedViewlet = typeof c === 'string' /* migration from pinned states to composites states */ ? { id: c, pinned: true, order: undefined, visible: true, name: undefined, icon: undefined, views: undefined } : c;
const storedStates: Array<string | ICachedViewContainer> = JSON.parse(value);
const cachedViewContainers = storedStates.map(c => {
const serialized: ICachedViewContainer = typeof c === 'string' /* migration from pinned states to composites states */ ? { id: c, pinned: true, order: undefined, visible: true, name: undefined, icon: undefined, views: undefined } : c;
serialized.visible = isUndefinedOrNull(serialized.visible) ? true : serialized.visible;
return serialized;
});
this.storeCachedViewletsState(cachedViewlets);
this.storeCachedViewContainersState(cachedViewContainers);
this.storageService.remove('workbench.activity.pinnedViewlets', StorageScope.GLOBAL);
}
}
+20 -8
View File
@@ -37,11 +37,11 @@ export class CompositeDragAndDrop implements ICompositeDragAndDrop {
constructor(
private viewDescriptorService: IViewDescriptorService,
private targetContainerLocation: ViewContainerLocation,
private openComposite: (id: string, focus?: boolean) => Promise<IPaneComposite | undefined>,
private openComposite: (id: string, focus?: boolean) => Promise<IPaneComposite | null>,
private moveComposite: (from: string, to: string, before?: Before2D) => void,
) { }
drop(data: CompositeDragAndDropData, targetCompositeId: string, originalEvent: DragEvent, before?: Before2D): void {
drop(data: CompositeDragAndDropData, targetCompositeId: string | undefined, originalEvent: DragEvent, before?: Before2D): void {
const dragData = data.getData();
if (dragData.type === 'composite') {
@@ -50,7 +50,9 @@ export class CompositeDragAndDrop implements ICompositeDragAndDrop {
// ... on the same composite bar
if (currentLocation === this.targetContainerLocation) {
this.moveComposite(dragData.id, targetCompositeId, before);
if (targetCompositeId) {
this.moveComposite(dragData.id, targetCompositeId, before);
}
}
// ... on a different composite bar
else {
@@ -60,7 +62,10 @@ export class CompositeDragAndDrop implements ICompositeDragAndDrop {
}
this.viewDescriptorService.moveViewContainerToLocation(currentContainer, this.targetContainerLocation);
this.moveComposite(currentContainer.id, targetCompositeId, before);
if (targetCompositeId) {
this.moveComposite(currentContainer.id, targetCompositeId, before);
}
this.openComposite(currentContainer.id, true);
}
@@ -74,7 +79,9 @@ export class CompositeDragAndDrop implements ICompositeDragAndDrop {
const newContainer = this.viewDescriptorService.getViewContainerByViewId(viewToMove.id)!;
this.moveComposite(newContainer.id, targetCompositeId, before);
if (targetCompositeId) {
this.moveComposite(newContainer.id, targetCompositeId, before);
}
this.openComposite(newContainer.id, true).then(composite => {
if (composite) {
@@ -140,7 +147,7 @@ export interface ICompositeBarOptions {
getOnCompositeClickAction: (compositeId: string) => Action;
getContextMenuActions: () => Action[];
getContextMenuActionsForComposite: (compositeId: string) => Action[];
openComposite: (compositeId: string) => Promise<IComposite | undefined>;
openComposite: (compositeId: string) => Promise<IComposite | null>;
getDefaultCompositeId: () => string;
hidePart: () => void;
}
@@ -188,6 +195,10 @@ export class CompositeBar extends Widget implements ICompositeBar {
return this.model.pinnedItems;
}
getVisibleComposites(): ICompositeBarItem[] {
return this.model.visibleItems;
}
create(parent: HTMLElement): HTMLElement {
const actionBarDiv = parent.appendChild($('.composite-bar'));
this.compositeSwitcherBar = this._register(new ActionBar(actionBarDiv, {
@@ -264,7 +275,8 @@ export class CompositeBar extends Widget implements ICompositeBar {
// Add to the model
if (this.model.add(id, name, order)) {
this.computeSizes([this.model.findItem(id)]);
this.updateCompositeSwitcher();
// Set timeout helps prevent flicker
setTimeout(() => this.updateCompositeSwitcher(), 0);
}
}
@@ -526,7 +538,7 @@ export class CompositeBar extends Widget implements ICompositeBar {
});
// Add overflow action as needed
if ((visibleCompositesChange && overflows) || compositeSwitcherBar.length() === 0) {
if ((visibleCompositesChange && overflows)) {
this.compositeOverflowAction = this.instantiationService.createInstance(CompositeOverflowActivityAction, () => {
if (this.compositeOverflowActionViewItem) {
this.compositeOverflowActionViewItem.showMenu();
@@ -91,7 +91,7 @@ class Item extends BreadcrumbsItem {
fileKind: this.element.kind,
fileDecorations: { colors: this.options.showDecorationColors, badges: false },
});
dom.addClass(container, FileKind[this.element.kind].toLowerCase());
container.classList.add(FileKind[this.element.kind].toLowerCase());
this._disposables.add(label);
} else if (this.element instanceof OutlineModel) {
@@ -113,7 +113,7 @@ class Item extends BreadcrumbsItem {
let icon = document.createElement('div');
icon.className = SymbolKinds.toCssClassName(this.element.symbol.kind);
container.appendChild(icon);
dom.addClass(container, 'shows-symbol-icon');
container.classList.add('shows-symbol-icon');
}
let label = new IconLabel(container);
let title = this.element.symbol.name.replace(/\r|\n|\r\n/g, '\u23CE');
@@ -183,7 +183,7 @@ export class BreadcrumbsControl {
@IBreadcrumbsService breadcrumbsService: IBreadcrumbsService,
) {
this.domNode = document.createElement('div');
dom.addClass(this.domNode, 'breadcrumbs-control');
this.domNode.classList.add('breadcrumbs-control');
dom.append(container, this.domNode);
this._cfUseQuickPick = BreadcrumbsConfig.UseQuickPick.bindTo(_configurationService);
@@ -221,13 +221,13 @@ export class BreadcrumbsControl {
}
isHidden(): boolean {
return dom.hasClass(this.domNode, 'hidden');
return this.domNode.classList.contains('hidden');
}
hide(): void {
this._breadcrumbsDisposables.clear();
this._ckBreadcrumbsVisible.set(false);
dom.toggleClass(this.domNode, 'hidden', true);
this.domNode.classList.toggle('hidden', true);
}
update(): boolean {
@@ -251,7 +251,7 @@ export class BreadcrumbsControl {
}
}
dom.toggleClass(this.domNode, 'hidden', false);
this.domNode.classList.toggle('hidden', false);
this._ckBreadcrumbsVisible.set(true);
this._ckBreadcrumbsPossible.set(true);
@@ -263,8 +263,8 @@ export class BreadcrumbsControl {
this._textResourceConfigurationService,
this._workspaceService
);
dom.toggleClass(this.domNode, 'relative-path', model.isRelative());
dom.toggleClass(this.domNode, 'backslash-path', this._labelService.getSeparator(uri.scheme, uri.authority) === '\\');
this.domNode.classList.toggle('relative-path', model.isRelative());
this.domNode.classList.toggle('backslash-path', this._labelService.getSeparator(uri.scheme, uri.authority) === '\\');
const updateBreadcrumbs = () => {
const showIcons = this._cfShowIcons.getValue();
@@ -3,7 +3,6 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as dom from 'vs/base/browser/dom';
import { compareFileNames } from 'vs/base/common/comparers';
import { onUnexpectedError } from 'vs/base/common/errors';
import { Emitter, Event } from 'vs/base/common/event';
@@ -375,11 +374,11 @@ export class BreadcrumbsFilePicker extends BreadcrumbsPicker {
_createTree(container: HTMLElement) {
// tree icon theme specials
dom.addClass(this._treeContainer, 'file-icon-themable-tree');
dom.addClass(this._treeContainer, 'show-file-icons');
this._treeContainer.classList.add('file-icon-themable-tree');
this._treeContainer.classList.add('show-file-icons');
const onFileIconThemeChange = (fileIconTheme: IFileIconTheme) => {
dom.toggleClass(this._treeContainer, 'align-icons-and-twisties', fileIconTheme.hasFileIcons && !fileIconTheme.hasFolderIcons);
dom.toggleClass(this._treeContainer, 'hide-arrows', fileIconTheme.hidesExplorerArrows === true);
this._treeContainer.classList.toggle('align-icons-and-twisties', fileIconTheme.hasFileIcons && !fileIconTheme.hasFolderIcons);
this._treeContainer.classList.toggle('hide-arrows', fileIconTheme.hidesExplorerArrows === true);
};
this._disposables.add(this._themeService.onDidFileIconThemeChange(onFileIconThemeChange));
onFileIconThemeChange(this._themeService.getFileIconTheme());
@@ -123,7 +123,7 @@ export class EditorControl extends Disposable {
private doInstantiateEditorPane(descriptor: IEditorDescriptor): BaseEditor {
// Return early if already instantiated
const existingEditorPane = this.editorPanes.filter(editorPane => descriptor.describes(editorPane))[0];
const existingEditorPane = this.editorPanes.find(editorPane => descriptor.describes(editorPane));
if (existingEditorPane) {
return existingEditorPane;
}
@@ -16,7 +16,6 @@ import { GroupDirection, MergeGroupMode } from 'vs/workbench/services/editor/com
import { toDisposable } from 'vs/base/common/lifecycle';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { RunOnceScheduler } from 'vs/base/common/async';
import { find } from 'vs/base/common/arrays';
import { DataTransfers } from 'vs/base/browser/dnd';
import { VSBuffer } from 'vs/base/common/buffer';
import { IFileDialogService } from 'vs/platform/dialogs/common/dialogs';
@@ -600,7 +599,7 @@ export class EditorDropTarget extends Themable {
private findTargetGroupView(child: HTMLElement): IEditorGroupView | undefined {
const groups = this.accessor.groups;
return find(groups, groupView => isAncestor(child, groupView.element) || this.delegate.groupContainsPredicate?.(groupView));
return groups.find(groupView => isAncestor(child, groupView.element) || this.delegate.groupContainsPredicate?.(groupView));
}
private updateContainer(isDraggedOver: boolean): void {

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