Archived
Merge from vscode bd0efff9e3f36d6b3e1045cee9887003af8034d7
This commit is contained in:
@@ -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}}
|
||||
@@ -1,6 +0,0 @@
|
||||
{
|
||||
"useTabs": true,
|
||||
"printWidth": 120,
|
||||
"semi": true,
|
||||
"singleQuote": true
|
||||
}
|
||||
@@ -1,3 +1,3 @@
|
||||
disturl "https://atom.io/download/electron"
|
||||
target "7.2.2"
|
||||
target "7.2.4"
|
||||
runtime "electron"
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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;
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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
@@ -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
@@ -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"
|
||||
|
||||
@@ -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
@@ -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
@@ -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
+1
-1
@@ -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);
|
||||
|
||||
+18
-1
@@ -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 });
|
||||
|
||||
@@ -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
@@ -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 !== ' ') {
|
||||
this.ui.title.innerHTML = ' ';
|
||||
}
|
||||
const description = this.getDescription();
|
||||
if (this.ui.description.textContent !== description) {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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');
|
||||
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
Vendored
+1
-1
@@ -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 {
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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 () {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
Vendored
+45
-2
@@ -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.
|
||||
*
|
||||
|
||||
Vendored
+66
-80
@@ -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 {
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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[] {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user