From 62d2fb534d24de42206fc8fe5e666d857ad4ceb1 Mon Sep 17 00:00:00 2001 From: Chris LaFreniere <40371649+chlafreniere@users.noreply.github.com> Date: Fri, 2 Aug 2019 21:06:44 -0700 Subject: [PATCH] Merge from vscode 709a07d51919d3266ca71699c6ddfb2d3547c0e1 (#6575) --- .../linux/continuous-build-linux.yml | 3 + .../linux/product-build-linux.yml | 15 ++-- build/azure-pipelines/product-build.yml | 3 +- build/azure-pipelines/web/publish.sh | 3 + .../win32/product-build-win32.yml | 1 + build/gulpfile.vscode.win32.js | 13 ++-- cglicenses.json | 26 +++++++ .../.vscode/launch.json | 10 ++- .../server/package.json | 2 +- .../json-language-features/server/yarn.lock | 15 ++-- .../theme-seti/icons/vs-seti-icon-theme.json | 6 +- package.json | 2 +- remote/package.json | 2 +- remote/yarn.lock | 8 +-- resources/win32/bin/code.sh | 3 +- scripts/code.sh | 2 +- .../browser/parts/views/customView.ts | 4 +- src/vs/base/browser/ui/dialog/dialog.ts | 1 + src/vs/base/browser/ui/list/listWidget.ts | 3 + src/vs/base/browser/ui/menu/menu.ts | 9 ++- src/vs/base/browser/ui/tree/abstractTree.ts | 15 ++-- src/vs/base/browser/ui/tree/asyncDataTree.ts | 6 +- src/vs/base/parts/ipc/common/ipc.ts | 4 +- src/vs/code/electron-main/app.ts | 3 - src/vs/code/electron-main/main.ts | 18 +++-- src/vs/code/node/cliProcessMain.ts | 16 ++++- .../editor/browser/widget/codeEditorWidget.ts | 5 +- .../editor/common/viewModel/viewModelImpl.ts | 5 +- .../contrib/codeAction/lightBulbWidget.ts | 2 +- .../standalone/browser/simpleServices.ts | 2 +- .../node/classification/typescript.test.ts | 7 +- src/vs/loader.js | 67 +++++++++++------- .../configuration/common/configuration.ts | 4 +- .../common/configurationModels.ts | 8 +-- .../contextview/browser/contextMenuHandler.ts | 4 ++ .../environment/node/environmentService.ts | 2 +- .../{node => common}/media/defaultIcon.png | Bin .../platform/menubar/electron-main/menubar.ts | 2 +- .../remote/common/remoteAgentConnection.ts | 7 +- src/vs/platform/sign/browser/signService.ts | 17 +---- src/vs/platform/windows/common/windows.ts | 1 + src/vs/vscode.d.ts | 2 +- src/vs/vscode.proposed.d.ts | 17 +++-- .../workbench/api/common/extHost.protocol.ts | 1 + .../workbench/api/common/extHostCommands.ts | 5 +- .../api/common/extHostConfiguration.ts | 4 +- .../api/node/extHostExtensionService.ts | 14 ++++ src/vs/workbench/api/node/extHostTask.ts | 8 ++- .../api/node/extHostTerminalService.ts | 5 +- .../browser/parts/titlebar/menubarControl.ts | 2 +- .../browser/parts/views/customView.ts | 34 +++++---- .../browser/parts/views/media/views.css | 1 + src/vs/workbench/browser/parts/views/views.ts | 3 +- src/vs/workbench/browser/web.main.ts | 5 +- .../workbench/browser/web.simpleservices.ts | 13 +++- .../browser/workbench.contribution.ts | 4 +- src/vs/workbench/browser/workbench.ts | 18 ++++- src/vs/workbench/common/views.ts | 2 +- .../browser/commentsEditorContribution.ts | 8 ++- .../contrib/comments/browser/media/review.css | 4 ++ .../contrib/debug/browser/debugCommands.ts | 2 +- .../extensions/browser/extensionsActions.ts | 21 ++++-- .../browser/extensionsDependencyChecker.ts | 2 +- .../extensions/browser/extensionsViewlet.ts | 6 +- .../browser/media/profile-start-dark.svg | 10 +-- .../browser/media/profile-start-light.svg | 10 +-- .../extensions/browser/media/start-dark.svg | 2 +- .../extensions/browser/media/start-light.svg | 2 +- .../browser/remoteExtensionsInstaller.ts | 12 ++-- .../extensionsActions.test.ts | 14 ++-- .../markers/browser/markersTreeViewer.ts | 31 ++++---- .../contrib/markers/browser/media/markers.css | 18 ++--- .../browser/media/settingsWidgets.css | 24 ++++++- .../preferences/browser/settingsEditor2.ts | 11 ++- .../preferences/browser/settingsTree.ts | 54 ++++++++------ .../preferences/browser/settingsWidgets.ts | 61 ++++++++++------ .../electron-browser/remote.contribution.ts | 21 ++++++ .../search/browser/search.contribution.ts | 63 ++++++++-------- .../tasks/browser/abstractTaskService.ts | 10 --- .../terminal/browser/terminal.contribution.ts | 3 + .../terminal/browser/terminalLinkHandler.ts | 1 + .../terminal/common/terminalEnvironment.ts | 34 ++++++--- .../terminalInstanceService.ts | 8 ++- .../contrib/terminal/node/terminal.ts | 11 +-- .../terminalLinkHandler.test.ts | 6 +- .../contrib/update/electron-browser/update.ts | 2 +- .../contrib/webview/common/themeing.ts | 4 +- .../environment/browser/environmentService.ts | 19 +++++ .../common/abstractExtensionService.ts | 5 ++ .../common/extensionHostProcessManager.ts | 9 +++ .../services/extensions/common/extensions.ts | 7 ++ .../common/remoteExtensionHostClient.ts | 1 - .../services/label/common/labelService.ts | 27 ++++--- .../services/label/test/label.test.ts | 60 ++++++++++++++++ .../remote/browser/remoteAgentServiceImpl.ts | 2 +- .../common/abstractRemoteAgentService.ts | 2 - .../remoteAgentServiceImpl.ts | 2 +- .../services/remote/node/tunnelService.ts | 1 - .../api/extHostConfiguration.test.ts | 24 +++---- test/smoke/src/areas/statusbar/statusbar.ts | 4 +- .../src/areas/workbench/data-loss.test.ts | 4 +- .../src/areas/workbench/localization.test.ts | 6 +- yarn.lock | 8 +-- 103 files changed, 726 insertions(+), 374 deletions(-) rename src/vs/platform/extensionManagement/{node => common}/media/defaultIcon.png (100%) diff --git a/build/azure-pipelines/linux/continuous-build-linux.yml b/build/azure-pipelines/linux/continuous-build-linux.yml index 997dceb9a4..8b0aaca2ad 100644 --- a/build/azure-pipelines/linux/continuous-build-linux.yml +++ b/build/azure-pipelines/linux/continuous-build-linux.yml @@ -46,6 +46,9 @@ steps: - script: | DISPLAY=:10 ./scripts/test.sh --tfs "Unit Tests" displayName: Run Unit Tests +- script: | + DISPLAY=:10 ./scripts/test-integration.sh --tfs "Integration Tests" + displayName: Run Integration Tests - task: PublishTestResults@2 displayName: Publish Tests Results inputs: diff --git a/build/azure-pipelines/linux/product-build-linux.yml b/build/azure-pipelines/linux/product-build-linux.yml index e97f5cfdef..dee07a95d7 100644 --- a/build/azure-pipelines/linux/product-build-linux.yml +++ b/build/azure-pipelines/linux/product-build-linux.yml @@ -93,16 +93,23 @@ steps: - script: | set -e - yarn gulp "electron-x64" - - # xvfb seems to be crashing often, let's make sure it's always up service xvfb start + displayName: Start xvfb + condition: and(succeeded(), eq(variables['VSCODE_STEP_ON_IT'], 'false')) +- script: | + set -e DISPLAY=:10 ./scripts/test.sh --build --tfs "Unit Tests" - # yarn smoketest -- --build "$(agent.builddirectory)/VSCode-linux-x64" displayName: Run unit tests condition: and(succeeded(), eq(variables['VSCODE_STEP_ON_IT'], 'false')) +- script: | + set -e + DISPLAY=:10 ./scripts/test-integration.sh --build --tfs "Integration Tests" + # yarn smoketest -- --build "$(agent.builddirectory)/VSCode-linux-x64" + displayName: Run integration tests + condition: and(succeeded(), eq(variables['VSCODE_STEP_ON_IT'], 'false')) + - script: | set -e AZURE_DOCUMENTDB_MASTERKEY="$(builds-docdb-key-readwrite)" \ diff --git a/build/azure-pipelines/product-build.yml b/build/azure-pipelines/product-build.yml index 469494c7d5..ad437466da 100644 --- a/build/azure-pipelines/product-build.yml +++ b/build/azure-pipelines/product-build.yml @@ -123,6 +123,7 @@ jobs: - LinuxSnap - LinuxArmhf - LinuxAlpine + - LinuxWeb - macOS steps: - template: sync-mooncake.yml @@ -132,4 +133,4 @@ schedules: displayName: Mon-Fri at 7:00 branches: include: - - master \ No newline at end of file + - master diff --git a/build/azure-pipelines/web/publish.sh b/build/azure-pipelines/web/publish.sh index 9d662fcfe8..2c112362a2 100755 --- a/build/azure-pipelines/web/publish.sh +++ b/build/azure-pipelines/web/publish.sh @@ -7,6 +7,9 @@ ROOT="$REPO/.." WEB_BUILD_NAME="vscode-web" WEB_TARBALL_FILENAME="vscode-web.tar.gz" WEB_TARBALL_PATH="$ROOT/$WEB_TARBALL_FILENAME" +BUILD="$ROOT/$WEB_BUILD_NAME" +PACKAGEJSON="$BUILD/package.json" +VERSION=$(node -p "require(\"$PACKAGEJSON\").version") rm -rf $ROOT/vscode-web.tar.* diff --git a/build/azure-pipelines/win32/product-build-win32.yml b/build/azure-pipelines/win32/product-build-win32.yml index 66583616c6..7a72dcfb09 100644 --- a/build/azure-pipelines/win32/product-build-win32.yml +++ b/build/azure-pipelines/win32/product-build-win32.yml @@ -99,6 +99,7 @@ steps: exec { yarn gulp "vscode-win32-$env:VSCODE_ARCH-min-ci" } exec { yarn gulp "vscode-reh-win32-$env:VSCODE_ARCH-min-ci" } exec { yarn gulp "vscode-reh-web-win32-$env:VSCODE_ARCH-min-ci" } + exec { yarn gulp "vscode-win32-$env:VSCODE_ARCH-code-helper" } exec { yarn gulp "vscode-win32-$env:VSCODE_ARCH-inno-updater" } displayName: Build diff --git a/build/gulpfile.vscode.win32.js b/build/gulpfile.vscode.win32.js index 8cd68d5361..e5e21e3058 100644 --- a/build/gulpfile.vscode.win32.js +++ b/build/gulpfile.vscode.win32.js @@ -136,12 +136,17 @@ function copyInnoUpdater(arch) { }; } -function patchInnoUpdater(arch) { +function updateIcon(executablePath) { return cb => { const icon = path.join(repoPath, 'resources', 'win32', 'code.ico'); - rcedit(path.join(buildPath(arch), 'tools', 'inno_updater.exe'), { icon }, cb); + rcedit(executablePath, { icon }, cb); }; } -gulp.task(task.define('vscode-win32-ia32-inno-updater', task.series(copyInnoUpdater('ia32'), patchInnoUpdater('ia32')))); -gulp.task(task.define('vscode-win32-x64-inno-updater', task.series(copyInnoUpdater('x64'), patchInnoUpdater('x64')))); \ No newline at end of file +gulp.task(task.define('vscode-win32-ia32-inno-updater', task.series(copyInnoUpdater('ia32'), updateIcon(path.join(buildPath('ia32'), 'tools', 'inno_updater.exe'))))); +gulp.task(task.define('vscode-win32-x64-inno-updater', task.series(copyInnoUpdater('x64'), updateIcon(path.join(buildPath('x64'), 'tools', 'inno_updater.exe'))))); + +// CodeHelper.exe icon + +gulp.task(task.define('vscode-win32-ia32-code-helper', task.series(updateIcon(path.join(buildPath('ia32'), 'resources', 'app', 'out', 'vs', 'platform', 'files', 'node', 'watcher', 'win32', 'CodeHelper.exe'))))); +gulp.task(task.define('vscode-win32-x64-code-helper', task.series(updateIcon(path.join(buildPath('x64'), 'resources', 'app', 'out', 'vs', 'platform', 'files', 'node', 'watcher', 'win32', 'CodeHelper.exe'))))); diff --git a/cglicenses.json b/cglicenses.json index 469cdedc9a..b7f408109b 100644 --- a/cglicenses.json +++ b/cglicenses.json @@ -743,5 +743,31 @@ "OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN", "THE SOFTWARE." ] + }, + { + "name": "atob", + "licenseDetail": [ + "The MIT License (MIT)", + "", + "Copyright (c) 2015 AJ ONeal", + "", + "Permission is hereby granted, free of charge, to any person obtaining a copy", + "of this software and associated documentation files (the \"Software\"), to deal", + "in the Software without restriction, including without limitation the rights", + "to use, copy, modify, merge, publish, distribute, sublicense, and/or sell", + "copies of the Software, and to permit persons to whom the Software is", + "furnished to do so, subject to the following conditions:", + "", + "The above copyright notice and this permission notice shall be included in all", + "copies or substantial portions of the Software.", + "", + "THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR", + "IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,", + "FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE", + "AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER", + "LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,", + "OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE", + "SOFTWARE." + ] } ] diff --git a/extensions/json-language-features/.vscode/launch.json b/extensions/json-language-features/.vscode/launch.json index b2d26ad6c3..bb5cde48bf 100644 --- a/extensions/json-language-features/.vscode/launch.json +++ b/extensions/json-language-features/.vscode/launch.json @@ -33,6 +33,14 @@ "sourceMaps": true, "outFiles": ["${workspaceFolder}/server/out"] } - + ], + "compounds": [ + { + "name": "Launch Extension and Attach Language Server", + "configurations": [ + "Launch Extension", + "Attach Language Server" + ] + } ] } \ No newline at end of file diff --git a/extensions/json-language-features/server/package.json b/extensions/json-language-features/server/package.json index 68e6a00553..bf5e3c8b09 100644 --- a/extensions/json-language-features/server/package.json +++ b/extensions/json-language-features/server/package.json @@ -14,7 +14,7 @@ "dependencies": { "jsonc-parser": "^2.1.0", "request-light": "^0.2.4", - "vscode-json-languageservice": "^3.3.0", + "vscode-json-languageservice": "^3.3.1", "vscode-languageserver": "^5.3.0-next.8", "vscode-nls": "^4.1.1", "vscode-uri": "^2.0.3" diff --git a/extensions/json-language-features/server/yarn.lock b/extensions/json-language-features/server/yarn.lock index 13ab8c59ab..3bfcb75ac7 100644 --- a/extensions/json-language-features/server/yarn.lock +++ b/extensions/json-language-features/server/yarn.lock @@ -73,15 +73,15 @@ request-light@^0.2.4: https-proxy-agent "^2.2.1" vscode-nls "^4.0.0" -vscode-json-languageservice@^3.3.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/vscode-json-languageservice/-/vscode-json-languageservice-3.3.0.tgz#f80ec21c19fb8648c815220a2857f9f0b22e1094" - integrity sha512-upq1PhwDItazdtRJ/R7uU0Fgrf9iaYa1xLK4WFLExR0DgbPojd0YgMpfyknVyXGlxsg3fJQ0H7J++QeByXHh9w== +vscode-json-languageservice@^3.3.1: + version "3.3.1" + resolved "https://registry.yarnpkg.com/vscode-json-languageservice/-/vscode-json-languageservice-3.3.1.tgz#4ad2c82db849a7bbe54fcbf5c9b3a2ed26dc8fee" + integrity sha512-Qyvlrftexu1acvwbMt+CDehVrDZtFV1GAJrKdOCHQL9bWNhzI06KEiSd4iXR0NUOuAdroG/uU4wBkH6e5CcTXg== dependencies: jsonc-parser "^2.1.0" vscode-languageserver-types "^3.15.0-next.2" vscode-nls "^4.1.1" - vscode-uri "^2.0.1" + vscode-uri "^2.0.3" vscode-jsonrpc@^4.1.0-next.2: version "4.1.0-next.2" @@ -130,11 +130,6 @@ vscode-uri@^1.0.6: resolved "https://registry.yarnpkg.com/vscode-uri/-/vscode-uri-1.0.6.tgz#6b8f141b0bbc44ad7b07e94f82f168ac7608ad4d" integrity sha512-sLI2L0uGov3wKVb9EB+vIQBl9tVP90nqRvxSoJ35vI3NjxE8jfsE5DSOhWgSunHSZmKS4OCi2jrtfxK7uyp2ww== -vscode-uri@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/vscode-uri/-/vscode-uri-2.0.1.tgz#5448e4f77d21d93ffa34b96f84c6c5e09e3f5a9b" - integrity sha512-s/k0zsYr6y+tsocFyxT/+G5aq8mEdpDZuph3LZ+UmCs7LNhx/xomiCy5kyP+jOAKC7RMCUvb6JbPD1/TgAvq0g== - vscode-uri@^2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/vscode-uri/-/vscode-uri-2.0.3.tgz#25e5f37f552fbee3cec7e5f80cef8469cefc6543" diff --git a/extensions/theme-seti/icons/vs-seti-icon-theme.json b/extensions/theme-seti/icons/vs-seti-icon-theme.json index d5a05b60ff..bdbbcb89ce 100644 --- a/extensions/theme-seti/icons/vs-seti-icon-theme.json +++ b/extensions/theme-seti/icons/vs-seti-icon-theme.json @@ -1627,7 +1627,7 @@ "bat": "_windows", "clojure": "_clojure", "coffeescript": "_coffee", - "jsonc": "_tsconfig", + "jsonc": "_json", "c": "_c", "cpp": "_cpp", "csharp": "_c-sharp", @@ -1896,7 +1896,7 @@ "bat": "_windows_light", "clojure": "_clojure_light", "coffeescript": "_coffee_light", - "jsonc": "_tsconfig_light", + "jsonc": "_json_light", "c": "_c_light", "cpp": "_cpp_light", "csharp": "_c-sharp_light", @@ -2012,4 +2012,4 @@ } }, "version": "https://github.com/jesseweed/seti-ui/commit/904c16acced1134a81b31d71d60293288c31334b" -} \ No newline at end of file +} diff --git a/package.json b/package.json index ca3d4a4349..f6e8f2bb2a 100644 --- a/package.json +++ b/package.json @@ -76,7 +76,7 @@ "vscode-ripgrep": "^1.5.5", "vscode-sqlite3": "4.0.8", "vscode-textmate": "^4.2.2", - "xterm": "3.15.0-beta89", + "xterm": "3.15.0-beta90", "xterm-addon-search": "0.2.0-beta3", "xterm-addon-web-links": "0.1.0-beta10", "yauzl": "^2.9.2", diff --git a/remote/package.json b/remote/package.json index 34ffee1a4b..5f851213c9 100644 --- a/remote/package.json +++ b/remote/package.json @@ -20,7 +20,7 @@ "vscode-proxy-agent": "0.4.0", "vscode-ripgrep": "^1.5.5", "vscode-textmate": "^4.2.2", - "xterm": "3.15.0-beta89", + "xterm": "3.15.0-beta90", "xterm-addon-search": "0.2.0-beta3", "xterm-addon-web-links": "0.1.0-beta10", "yauzl": "^2.9.2", diff --git a/remote/yarn.lock b/remote/yarn.lock index 1c4e700f49..019b237911 100644 --- a/remote/yarn.lock +++ b/remote/yarn.lock @@ -1159,10 +1159,10 @@ xterm-addon-web-links@0.1.0-beta10: resolved "https://registry.yarnpkg.com/xterm-addon-web-links/-/xterm-addon-web-links-0.1.0-beta10.tgz#610fa9773a2a5ccd41c1c83ba0e2dd2c9eb66a23" integrity sha512-xfpjy0V6bB4BR44qIgZQPoCMVakxb65gMscPkHpO//QxvUxKzabV3dxOsIbeZRFkUGsWTFlvz2OoaBLoNtv5gg== -xterm@3.15.0-beta89: - version "3.15.0-beta89" - resolved "https://registry.yarnpkg.com/xterm/-/xterm-3.15.0-beta89.tgz#255962e2595deefb42b8c0043001256526163a3f" - integrity sha512-rNaoUamacPRg+ejbKDGRDNqR3SZ3Uf/pUW0mO+FF25/lIgdLq8x7RgZVBgFweCZ/dijPjxoyMcgfNDTH9h8LOg== +xterm@3.15.0-beta90: + version "3.15.0-beta90" + resolved "https://registry.yarnpkg.com/xterm/-/xterm-3.15.0-beta90.tgz#e1732c2914584c86cffa797ba762c482f21ce182" + integrity sha512-eixIA5brfoez+Y8bJPCcIw8Q7LgOvxRX3cPBaGmo7ozUASx9IEGOmvIRQX1ozTUmxEiXPnAxOfl/isQ+yNlaww== yauzl@^2.9.2: version "2.10.0" diff --git a/resources/win32/bin/code.sh b/resources/win32/bin/code.sh index 9c5eb1c8b1..23a4001a47 100644 --- a/resources/win32/bin/code.sh +++ b/resources/win32/bin/code.sh @@ -34,8 +34,7 @@ if grep -qi Microsoft /proc/version; then if [ -n "$WSL_EXT_WLOC" ]; then # replace \r\n with \n in WSL_EXT_WLOC WSL_CODE=$(wslpath -u "${WSL_EXT_WLOC%%[[:cntrl:]]}")/scripts/wslCode.sh - WIN_CODE_CMD=$(wslpath -w "$VSCODE_PATH/bin/$APP_NAME.cmd") - "$WSL_CODE" "$COMMIT" "$QUALITY" "$WIN_CODE_CMD" "$APP_NAME" "$DATAFOLDER" "$@" + "$WSL_CODE" "$COMMIT" "$QUALITY" "$ELECTRON" "$APP_NAME" "$DATAFOLDER" "$@" exit $? fi else diff --git a/scripts/code.sh b/scripts/code.sh index 830271adff..542efab523 100755 --- a/scripts/code.sh +++ b/scripts/code.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash -set -ex +set -e if [[ "$OSTYPE" == "darwin"* ]]; then realpath() { [[ $1 = /* ]] && echo "$1" || echo "$PWD/${1#./}"; } diff --git a/src/sql/workbench/browser/parts/views/customView.ts b/src/sql/workbench/browser/parts/views/customView.ts index 30508a1521..a547a22be5 100644 --- a/src/sql/workbench/browser/parts/views/customView.ts +++ b/src/sql/workbench/browser/parts/views/customView.ts @@ -79,8 +79,8 @@ export class CustomTreeViewPanel extends ViewletPanel { this.treeView.show(container); } - layoutBody(size: number): void { - this.treeView.layout(size); + layoutBody(height: number, width: number): void { + this.treeView.layout(height, width); } getActions(): IAction[] { diff --git a/src/vs/base/browser/ui/dialog/dialog.ts b/src/vs/base/browser/ui/dialog/dialog.ts index e0ae7ed4ad..4d3d1e59ff 100644 --- a/src/vs/base/browser/ui/dialog/dialog.ts +++ b/src/vs/base/browser/ui/dialog/dialog.ts @@ -195,6 +195,7 @@ export class Dialog extends Disposable { this.applyStyles(); + this.element.setAttribute('aria-label', this.message); show(this.element); // Focus first element diff --git a/src/vs/base/browser/ui/list/listWidget.ts b/src/vs/base/browser/ui/list/listWidget.ts index 813e7c207d..d7a26fc88f 100644 --- a/src/vs/base/browser/ui/list/listWidget.ts +++ b/src/vs/base/browser/ui/list/listWidget.ts @@ -647,12 +647,15 @@ export class MouseController implements IDisposable { } const newSelection = disjunction(rangeSelection, relativeComplement(selection, contiguousRange)); + this.list.setFocus([focus]); this.list.setSelection(newSelection, e.browserEvent); } else if (this.isSelectionSingleChangeEvent(e)) { const selection = this.list.getSelection(); const newSelection = selection.filter(i => i !== focus); + this.list.setFocus([focus]); + if (selection.length === newSelection.length) { this.list.setSelection([...newSelection, focus], e.browserEvent); } else { diff --git a/src/vs/base/browser/ui/menu/menu.ts b/src/vs/base/browser/ui/menu/menu.ts index bf4f136f53..2ca7b6de23 100644 --- a/src/vs/base/browser/ui/menu/menu.ts +++ b/src/vs/base/browser/ui/menu/menu.ts @@ -626,8 +626,11 @@ class SubmenuMenuActionViewItem extends BaseMenuActionViewItem { this._register(addDisposableListener(this.element, EventType.KEY_DOWN, e => { let event = new StandardKeyboardEvent(e); - if (event.equals(KeyCode.RightArrow) || event.equals(KeyCode.Enter)) { - EventHelper.stop(e, true); + + if (document.activeElement === this.item) { + if (event.equals(KeyCode.RightArrow) || event.equals(KeyCode.Enter)) { + EventHelper.stop(e, true); + } } })); @@ -802,4 +805,4 @@ export function cleanMnemonic(label: string): string { const mnemonicInText = matches[0].charAt(0) === '&'; return label.replace(regex, mnemonicInText ? '$2' : '').trim(); -} \ No newline at end of file +} diff --git a/src/vs/base/browser/ui/tree/abstractTree.ts b/src/vs/base/browser/ui/tree/abstractTree.ts index e259642cc6..38ab665b13 100644 --- a/src/vs/base/browser/ui/tree/abstractTree.ts +++ b/src/vs/base/browser/ui/tree/abstractTree.ts @@ -244,7 +244,7 @@ class TreeRenderer implements IListRenderer, HTMLDivElement>(); - private activeParentNodes = new Set>(); + private activeIndentNodes = new Set>(); private indentGuidesDisposable: IDisposable = Disposable.None; private disposables: IDisposable[] = []; @@ -353,6 +353,7 @@ class TreeRenderer implements IListRenderer implements IListRenderer('.indent-guide', { style: `width: ${this.indent}px` }); - if (this.activeParentNodes.has(parent)) { + if (this.activeIndentNodes.has(parent)) { addClass(guide, 'active'); } @@ -413,24 +414,26 @@ class TreeRenderer implements IListRenderer>(); nodes.forEach(node => { - if (node.parent) { + if (node.collapsible && node.children.length > 0 && !node.collapsed) { + set.add(node); + } else if (node.parent) { set.add(node.parent); } }); - this.activeParentNodes.forEach(node => { + this.activeIndentNodes.forEach(node => { if (!set.has(node)) { this.renderedIndentGuides.forEach(node, line => removeClass(line, 'active')); } }); set.forEach(node => { - if (!this.activeParentNodes.has(node)) { + if (!this.activeIndentNodes.has(node)) { this.renderedIndentGuides.forEach(node, line => addClass(line, 'active')); } }); - this.activeParentNodes = set; + this.activeIndentNodes = set; } dispose(): void { diff --git a/src/vs/base/browser/ui/tree/asyncDataTree.ts b/src/vs/base/browser/ui/tree/asyncDataTree.ts index 2ba29ad9bc..ce6b4122a9 100644 --- a/src/vs/base/browser/ui/tree/asyncDataTree.ts +++ b/src/vs/base/browser/ui/tree/asyncDataTree.ts @@ -477,7 +477,7 @@ export class AsyncDataTree implements IDisposable // View rerender(element?: T): void { - if (element === undefined) { + if (element === undefined || element === this.root.element) { this.tree.rerender(); return; } @@ -602,9 +602,9 @@ export class AsyncDataTree implements IDisposable return nodes.map(n => n!.element as T); } - open(elements: T[]): void { + open(elements: T[], browserEvent?: UIEvent): void { const nodes = elements.map(e => this.getDataNode(e)); - this.tree.open(nodes); + this.tree.open(nodes, browserEvent); } reveal(element: T, relativeTop?: number): void { diff --git a/src/vs/base/parts/ipc/common/ipc.ts b/src/vs/base/parts/ipc/common/ipc.ts index 45d68976b9..f9708d4e15 100644 --- a/src/vs/base/parts/ipc/common/ipc.ts +++ b/src/vs/base/parts/ipc/common/ipc.ts @@ -268,7 +268,9 @@ export class ChannelServer implements IChannelServer): void { this.channels.set(channelName, channel); - this.flushPendingRequests(channelName); + + // https://github.com/microsoft/vscode/issues/72531 + setTimeout(() => this.flushPendingRequests(channelName), 0); } private sendResponse(response: IRawResponse): void { diff --git a/src/vs/code/electron-main/app.ts b/src/vs/code/electron-main/app.ts index 133fe903b5..a77e6a61eb 100644 --- a/src/vs/code/electron-main/app.ts +++ b/src/vs/code/electron-main/app.ts @@ -697,8 +697,6 @@ export class CodeApplication extends Disposable { private handleRemoteAuthorities(): void { const connectionPool: Map = new Map(); - const isBuilt = this.environmentService.isBuilt; - class ActiveConnection { private readonly _authority: string; private readonly _connection: Promise; @@ -708,7 +706,6 @@ export class CodeApplication extends Disposable { this._authority = authority; const options: IConnectionOptions = { - isBuilt, commit: product.commit, socketFactory: nodeSocketFactory, addressProvider: { diff --git a/src/vs/code/electron-main/main.ts b/src/vs/code/electron-main/main.ts index 647ce03a82..c39a115f8d 100644 --- a/src/vs/code/electron-main/main.ts +++ b/src/vs/code/electron-main/main.ts @@ -23,7 +23,7 @@ import { ILogService, ConsoleLogMainService, MultiplexLogService, getLogLevel } import { StateService } from 'vs/platform/state/node/stateService'; import { IStateService } from 'vs/platform/state/common/state'; import { IEnvironmentService, ParsedArgs } from 'vs/platform/environment/common/environment'; -import { EnvironmentService } from 'vs/platform/environment/node/environmentService'; +import { EnvironmentService, xdgRuntimeDir } from 'vs/platform/environment/node/environmentService'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { ConfigurationService } from 'vs/platform/configuration/node/configurationService'; import { IRequestService } from 'vs/platform/request/common/request'; @@ -332,11 +332,19 @@ class CodeMain { private handleStartupDataDirError(environmentService: IEnvironmentService, error: NodeJS.ErrnoException): void { if (error.code === 'EACCES' || error.code === 'EPERM') { + const directories = [environmentService.userDataPath]; + + if (environmentService.extensionsPath) { + directories.push(environmentService.extensionsPath); + } + + if (xdgRuntimeDir) { + directories.push(xdgRuntimeDir); + } + this.showStartupWarningDialog( localize('startupDataDirError', "Unable to write program user data."), - environmentService.extensionsPath - ? localize('startupUserDataAndExtensionsDirErrorDetail', "Please make sure the directories {0} and {1} are writeable.", environmentService.userDataPath, environmentService.extensionsPath) - : localize('startupUserDataDirErrorDetail', "Please make sure the directory {0} is writeable.", environmentService.userDataPath) + localize('startupUserDataAndExtensionsDirErrorDetail', "Please make sure the following directories are writeable:\n\n{0}", directories.join('\n')) ); } } @@ -394,4 +402,4 @@ class CodeMain { // Main Startup const code = new CodeMain(); -code.main(); \ No newline at end of file +code.main(); diff --git a/src/vs/code/node/cliProcessMain.ts b/src/vs/code/node/cliProcessMain.ts index 164db194d5..6ddf0125e8 100644 --- a/src/vs/code/node/cliProcessMain.ts +++ b/src/vs/code/node/cliProcessMain.ts @@ -112,7 +112,13 @@ export class Main { private async listExtensions(showVersions: boolean, category?: string): Promise { let extensions = await this.extensionManagementService.getInstalled(ExtensionType.User); - if (category) { + // TODO: we should save this array in a common place so that the command and extensionQuery can use it that way changing it is easier + const categories = ['"programming languages"', 'snippets', 'linters', 'themes', 'debuggers', 'formatters', 'keymaps', '"scm providers"', 'other', '"extension packs"', '"language packs"']; + if (category && category !== '') { + if (categories.indexOf(category.toLowerCase()) < 0) { + console.log('Invalid category please enter a valid category. To list valid categories run --category without a category specified'); + return; + } extensions = extensions.filter(e => { if (e.manifest.categories) { const lowerCaseCategories: string[] = e.manifest.categories.map(c => c.toLowerCase()); @@ -120,6 +126,12 @@ export class Main { } return false; }); + } else if (category === '') { + console.log('Possible Categories: '); + categories.forEach(category => { + console.log(category); + }); + return; } extensions.forEach(e => console.log(getId(e.manifest, showVersions))); } @@ -369,4 +381,4 @@ export async function main(argv: ParsedArgs): Promise { disposables.dispose(); } }); -} \ No newline at end of file +} diff --git a/src/vs/editor/browser/widget/codeEditorWidget.ts b/src/vs/editor/browser/widget/codeEditorWidget.ts index 0223a9b2ec..6f083a7672 100644 --- a/src/vs/editor/browser/widget/codeEditorWidget.ts +++ b/src/vs/editor/browser/widget/codeEditorWidget.ts @@ -39,7 +39,7 @@ import { ModelDecorationOptions } from 'vs/editor/common/model/textModel'; import { IModelContentChangedEvent, IModelDecorationsChangedEvent, IModelLanguageChangedEvent, IModelLanguageConfigurationChangedEvent, IModelOptionsChangedEvent } from 'vs/editor/common/model/textModelEvents'; import * as modes from 'vs/editor/common/modes'; import { editorUnnecessaryCodeBorder, editorUnnecessaryCodeOpacity } from 'vs/editor/common/view/editorColorRegistry'; -import { editorErrorBorder, editorErrorForeground, editorHintBorder, editorHintForeground, editorInfoBorder, editorInfoForeground, editorWarningBorder, editorWarningForeground } from 'vs/platform/theme/common/colorRegistry'; +import { editorErrorBorder, editorErrorForeground, editorHintBorder, editorHintForeground, editorInfoBorder, editorInfoForeground, editorWarningBorder, editorWarningForeground, editorForeground } from 'vs/platform/theme/common/colorRegistry'; import { VerticalRevealType } from 'vs/editor/common/view/viewEvents'; import { IEditorWhitespace } from 'vs/editor/common/viewLayout/whitespaceComputer'; import { ViewModel } from 'vs/editor/common/viewModel/viewModelImpl'; @@ -1849,5 +1849,6 @@ registerThemingParticipant((theme, collector) => { collector.addRule(`.${SHOW_UNUSED_ENABLED_CLASS} .monaco-editor .${ClassName.EditorUnnecessaryDecoration} { border-bottom: 2px dashed ${unnecessaryBorder}; }`); } - collector.addRule(`.monaco-editor .${ClassName.EditorDeprecatedInlineDecoration} { text-decoration: line-through; }`); + const deprecatedForeground = theme.getColor(editorForeground) || 'inherit'; + collector.addRule(`.monaco-editor .${ClassName.EditorDeprecatedInlineDecoration} { text-decoration: line-through; text-decoration-color: ${deprecatedForeground}}`); }); diff --git a/src/vs/editor/common/viewModel/viewModelImpl.ts b/src/vs/editor/common/viewModel/viewModelImpl.ts index 47729c8921..64924cd197 100644 --- a/src/vs/editor/common/viewModel/viewModelImpl.ts +++ b/src/vs/editor/common/viewModel/viewModelImpl.ts @@ -6,7 +6,7 @@ import { Color } from 'vs/base/common/color'; import { IDisposable } from 'vs/base/common/lifecycle'; import * as strings from 'vs/base/common/strings'; -import { IConfigurationChangedEvent } from 'vs/editor/common/config/editorOptions'; +import { IConfigurationChangedEvent, EDITOR_FONT_DEFAULTS } from 'vs/editor/common/config/editorOptions'; import { IPosition, Position } from 'vs/editor/common/core/position'; import { IRange, Range } from 'vs/editor/common/core/range'; import * as editorCommon from 'vs/editor/common/editorCommon'; @@ -668,12 +668,13 @@ export class ViewModel extends viewEvents.ViewEventEmitter implements IViewModel const fontInfo = this.configuration.editor.fontInfo; const colorMap = this._getColorMap(); + const fontFamily = fontInfo.fontFamily === EDITOR_FONT_DEFAULTS.fontFamily ? fontInfo.fontFamily : `'${fontInfo.fontFamily}', ${EDITOR_FONT_DEFAULTS.fontFamily}`; return ( `
{ + folders: this._folderConfigurations.keys().reduce<[UriComponents, IConfigurationModel][]>((result, folder) => { const { contents, overrides, keys } = this._folderConfigurations.get(folder)!; - result[folder.toString()] = { contents, overrides, keys }; + result.push([folder, { contents, overrides, keys }]); return result; - }, Object.create({})) + }, []) }; } diff --git a/src/vs/platform/contextview/browser/contextMenuHandler.ts b/src/vs/platform/contextview/browser/contextMenuHandler.ts index b7639157d7..4dd3fddd43 100644 --- a/src/vs/platform/contextview/browser/contextMenuHandler.ts +++ b/src/vs/platform/contextview/browser/contextMenuHandler.ts @@ -85,6 +85,10 @@ export class ContextMenuHandler { menu.onDidBlur(() => this.contextViewService.hideContextView(true), null, menuDisposables); domEvent(window, EventType.BLUR)(() => { this.contextViewService.hideContextView(true); }, null, menuDisposables); domEvent(window, EventType.MOUSE_DOWN)((e: MouseEvent) => { + if (e.defaultPrevented) { + return; + } + let event = new StandardMouseEvent(e); let element: HTMLElement | null = event.target; diff --git a/src/vs/platform/environment/node/environmentService.ts b/src/vs/platform/environment/node/environmentService.ts index d7e1af56b1..c9e85ebc17 100644 --- a/src/vs/platform/environment/node/environmentService.ts +++ b/src/vs/platform/environment/node/environmentService.ts @@ -19,7 +19,7 @@ import { URI } from 'vs/base/common/uri'; // Read this before there's any chance it is overwritten // Related to https://github.com/Microsoft/vscode/issues/30624 -const xdgRuntimeDir = process.env['XDG_RUNTIME_DIR']; +export const xdgRuntimeDir = process.env['XDG_RUNTIME_DIR']; function getNixIPCHandle(userDataPath: string, type: string): string { const vscodePortable = process.env['VSCODE_PORTABLE']; diff --git a/src/vs/platform/extensionManagement/node/media/defaultIcon.png b/src/vs/platform/extensionManagement/common/media/defaultIcon.png similarity index 100% rename from src/vs/platform/extensionManagement/node/media/defaultIcon.png rename to src/vs/platform/extensionManagement/common/media/defaultIcon.png diff --git a/src/vs/platform/menubar/electron-main/menubar.ts b/src/vs/platform/menubar/electron-main/menubar.ts index 31b14a816e..9a909d4a85 100644 --- a/src/vs/platform/menubar/electron-main/menubar.ts +++ b/src/vs/platform/menubar/electron-main/menubar.ts @@ -559,7 +559,7 @@ export class Menubar { })]; case StateType.CheckingForUpdates: - return [new MenuItem({ label: nls.localize('miCheckingForUpdates', "Checking For Updates..."), enabled: false })]; + return [new MenuItem({ label: nls.localize('miCheckingForUpdates', "Checking for Updates..."), enabled: false })]; case StateType.AvailableForDownload: return [new MenuItem({ diff --git a/src/vs/platform/remote/common/remoteAgentConnection.ts b/src/vs/platform/remote/common/remoteAgentConnection.ts index f9c49f51d8..45ae5a21f8 100644 --- a/src/vs/platform/remote/common/remoteAgentConnection.ts +++ b/src/vs/platform/remote/common/remoteAgentConnection.ts @@ -35,7 +35,6 @@ export interface ConnectionTypeRequest { signedData?: string; desiredConnectionType?: ConnectionType; args?: any; - isBuilt: boolean; } export interface ErrorMessage { @@ -51,7 +50,6 @@ export type HandshakeMessage = AuthRequest | SignRequest | ConnectionTypeRequest interface ISimpleConnectionOptions { - isBuilt: boolean; commit: string | undefined; host: string; port: number; @@ -110,8 +108,7 @@ async function connectToRemoteExtensionHostAgent(options: ISimpleConnectionOptio type: 'connectionType', commit: options.commit, signedData: signed, - desiredConnectionType: connectionType, - isBuilt: options.isBuilt + desiredConnectionType: connectionType }; if (args) { connTypeRequest.args = args; @@ -200,7 +197,6 @@ async function doConnectRemoteAgentTunnel(options: ISimpleConnectionOptions, sta } export interface IConnectionOptions { - isBuilt: boolean; commit: string | undefined; socketFactory: ISocketFactory; addressProvider: IAddressProvider; @@ -210,7 +206,6 @@ export interface IConnectionOptions { async function resolveConnectionOptions(options: IConnectionOptions, reconnectionToken: string, reconnectionProtocol: PersistentProtocol | null): Promise { const { host, port } = await options.addressProvider.getAddress(); return { - isBuilt: options.isBuilt, commit: options.commit, host: host, port: port, diff --git a/src/vs/platform/sign/browser/signService.ts b/src/vs/platform/sign/browser/signService.ts index 53e39a2e4e..2ca9f40f0f 100644 --- a/src/vs/platform/sign/browser/signService.ts +++ b/src/vs/platform/sign/browser/signService.ts @@ -13,22 +13,7 @@ export class SignService implements ISignService { private readonly _tkn: string | null; constructor(token: string | undefined) { - if (typeof token !== 'undefined') { - this._tkn = token; - } else { - this._tkn = SignService._readTokenFromURL(); - } - } - - private static _readTokenFromURL(): string | null { - if (!document.location.hash) { - return null; - } - const m = document.location.hash.match(/[#&]tkn=([^&]+)/); - if (!m) { - return null; - } - return m[1]; + this._tkn = token || null; } async sign(value: string): Promise { diff --git a/src/vs/platform/windows/common/windows.ts b/src/vs/platform/windows/common/windows.ts index f6d12853a6..29c6aed88a 100644 --- a/src/vs/platform/windows/common/windows.ts +++ b/src/vs/platform/windows/common/windows.ts @@ -444,6 +444,7 @@ export interface IWindowConfiguration extends ParsedArgs { filesToDiff?: IPath[]; filesToWait?: IPathsToWaitFor; termProgram?: string; + connectionToken?: string; } export interface IRunActionInWindowRequest { diff --git a/src/vs/vscode.d.ts b/src/vs/vscode.d.ts index 02d5c89db6..0ad45e6738 100644 --- a/src/vs/vscode.d.ts +++ b/src/vs/vscode.d.ts @@ -5454,7 +5454,7 @@ declare module 'vscode' { * from `tasks.json` files as well as tasks from task providers * contributed through extensions. * - * @param filter a filter to filter the return tasks. + * @param filter Optional filter to select tasks of a certain type or version. */ export function fetchTasks(filter?: TaskFilter): Thenable; diff --git a/src/vs/vscode.proposed.d.ts b/src/vs/vscode.proposed.d.ts index 68900ed47f..33d3d95813 100644 --- a/src/vs/vscode.proposed.d.ts +++ b/src/vs/vscode.proposed.d.ts @@ -983,19 +983,19 @@ declare module 'vscode' { /** * An event that when fired allows overriding the [dimensions](#Terminal.dimensions) of the - * terminal. Note that when set the overridden dimensions will only take effect when they + * terminal. Note that when set, the overridden dimensions will only take effect when they * are lower than the actual dimensions of the terminal (ie. there will never be a scroll * bar). Set to `undefined` for the terminal to go back to the regular dimensions (fit to * the size of the panel). * * **Example:** Override the dimensions of a terminal to 20 columns and 10 rows * ```typescript - * const dimensionsEmitter = new vscode.EventEmitter(); + * const dimensionsEmitter = new vscode.EventEmitter(); * const pty: vscode.Pseudoterminal = { * onDidWrite: writeEmitter.event, * onDidOverrideDimensions: dimensionsEmitter.event, * open: () => { - * dimensionsEmitter.fire({ + * dimensionsEmitter.fire({ * columns: 20, * rows: 10 * }); @@ -1013,17 +1013,17 @@ declare module 'vscode' { * **Example:** Exit the terminal when "y" is pressed, otherwise show a notification. * ```typescript * const writeEmitter = new vscode.EventEmitter(); - * const closeEmitter = new vscode.EventEmitter(); + * const closeEmitter = new vscode.EventEmitter(); * const pty: vscode.Pseudoterminal = { * onDidWrite: writeEmitter.event, * onDidClose: closeEmitter.event, * open: () => writeEmitter.fire('Press y to exit successfully'), * close: () => {} - * handleInput: { + * handleInput: data => { * if (data !== 'y') { * vscode.window.showInformationMessage('Something went wrong'); * } - * data => closeEmitter.fire(); + * closeEmitter.fire(); * } * }; * vscode.window.createTerminal({ name: 'Exit example', pty }); @@ -1071,6 +1071,11 @@ declare module 'vscode' { * state of a terminal's dimensions should be treated as `undefined` until this is triggered * as the size of a terminal isn't know until it shows up in the user interface. * + * When dimensions are overridden by + * [onDidOverrideDimensions](#Pseudoterminal.onDidOverrideDimensions), `setDimensions` will + * continue to be called with the regular panel dimensions, allowing the extension continue + * to react dimension changes. + * * @param dimensions The new dimensions. */ setDimensions?(dimensions: TerminalDimensions): void; diff --git a/src/vs/workbench/api/common/extHost.protocol.ts b/src/vs/workbench/api/common/extHost.protocol.ts index 9d3c1c4b84..836368075c 100644 --- a/src/vs/workbench/api/common/extHost.protocol.ts +++ b/src/vs/workbench/api/common/extHost.protocol.ts @@ -880,6 +880,7 @@ export interface ExtHostExtensionServiceShape { $startExtensionHost(enabledExtensionIds: ExtensionIdentifier[]): Promise; $activateByEvent(activationEvent: string): Promise; $activate(extensionId: ExtensionIdentifier, activationEvent: string): Promise; + $setRemoteEnvironment(env: { [key: string]: string | null }): Promise; $deltaExtensions(toAdd: IExtensionDescription[], toRemove: ExtensionIdentifier[]): Promise; diff --git a/src/vs/workbench/api/common/extHostCommands.ts b/src/vs/workbench/api/common/extHostCommands.ts index edb1bc5ad1..bdb10ed50d 100644 --- a/src/vs/workbench/api/common/extHostCommands.ts +++ b/src/vs/workbench/api/common/extHostCommands.ts @@ -128,7 +128,9 @@ export class ExtHostCommands implements ExtHostCommandsShape { if (this._commands.has(id)) { // we stay inside the extension host and support // to pass any kind of parameters around - return this._executeContributedCommand(id, args); + const res = this._executeContributedCommand(id, args); + this._onDidExecuteCommand.fire({ command: id, arguments: args }); + return res; } else { // automagically convert some argument types @@ -170,7 +172,6 @@ export class ExtHostCommands implements ExtHostCommandsShape { try { const result = callback.apply(thisArg, args); - this._onDidExecuteCommand.fire({ command: id, arguments: args }); return Promise.resolve(result); } catch (err) { this._logService.error(err, id); diff --git a/src/vs/workbench/api/common/extHostConfiguration.ts b/src/vs/workbench/api/common/extHostConfiguration.ts index e0cd27b86b..33cfce44b6 100644 --- a/src/vs/workbench/api/common/extHostConfiguration.ts +++ b/src/vs/workbench/api/common/extHostConfiguration.ts @@ -263,8 +263,8 @@ export class ExtHostConfigProvider { const defaultConfiguration = ExtHostConfigProvider.parseConfigurationModel(data.defaults); const userConfiguration = ExtHostConfigProvider.parseConfigurationModel(data.user); const workspaceConfiguration = ExtHostConfigProvider.parseConfigurationModel(data.workspace); - const folders: ResourceMap = Object.keys(data.folders).reduce((result, key) => { - result.set(URI.parse(key), ExtHostConfigProvider.parseConfigurationModel(data.folders[key])); + const folders: ResourceMap = data.folders.reduce((result, value) => { + result.set(URI.revive(value[0]), ExtHostConfigProvider.parseConfigurationModel(value[1])); return result; }, new ResourceMap()); return new Configuration(defaultConfiguration, userConfiguration, new ConfigurationModel(), workspaceConfiguration, folders, new ConfigurationModel(), new ResourceMap(), false); diff --git a/src/vs/workbench/api/node/extHostExtensionService.ts b/src/vs/workbench/api/node/extHostExtensionService.ts index fdbc343074..dd6790853e 100644 --- a/src/vs/workbench/api/node/extHostExtensionService.ts +++ b/src/vs/workbench/api/node/extHostExtensionService.ts @@ -767,6 +767,20 @@ export class ExtHostExtensionService implements ExtHostExtensionServiceShape { return buff; } + public async $setRemoteEnvironment(env: { [key: string]: string | null }): Promise { + if (!this._initData.remote.isRemote) { + return; + } + + for (const key in env) { + const value = env[key]; + if (value === null) { + delete process.env[key]; + } else { + process.env[key] = value; + } + } + } } function loadCommonJSModule(logService: ILogService, modulePath: string, activationTimesBuilder: ExtensionActivationTimesBuilder): Promise { diff --git a/src/vs/workbench/api/node/extHostTask.ts b/src/vs/workbench/api/node/extHostTask.ts index 9e011a7eb6..360f441581 100644 --- a/src/vs/workbench/api/node/extHostTask.ts +++ b/src/vs/workbench/api/node/extHostTask.ts @@ -743,12 +743,16 @@ export class ExtHostTask implements ExtHostTaskShape { throw new Error('Unexpected: Task cannot be resolved.'); } + if (resolvedTask.definition !== task.definition) { + throw new Error('Unexpected: The resolved task definition must be the same object as the original task definition. The task definition cannot be changed.'); + } + if (CustomExecutionDTO.is(resolvedTaskDTO.execution)) { - await this.addCustomExecution(taskDTO, task); + await this.addCustomExecution(resolvedTaskDTO, resolvedTask); } if (CustomExecution2DTO.is(resolvedTaskDTO.execution)) { - await this.addCustomExecution2(taskDTO, task); + await this.addCustomExecution2(resolvedTaskDTO, resolvedTask); } return resolvedTaskDTO;*/ diff --git a/src/vs/workbench/api/node/extHostTerminalService.ts b/src/vs/workbench/api/node/extHostTerminalService.ts index 92185f1089..af0fdf1f86 100644 --- a/src/vs/workbench/api/node/extHostTerminalService.ts +++ b/src/vs/workbench/api/node/extHostTerminalService.ts @@ -371,7 +371,8 @@ export class ExtHostTerminalService implements ExtHostTerminalServiceShape { process.env.hasOwnProperty('PROCESSOR_ARCHITEW6432'), process.env.windir, this._lastActiveWorkspace, - this._variableResolver + this._variableResolver, + this._logService ); } @@ -383,7 +384,7 @@ export class ExtHostTerminalService implements ExtHostTerminalServiceShape { return this._apiInspectConfigToPlain(setting); }; - return terminalEnvironment.getDefaultShellArgs(fetchSetting, this._isWorkspaceShellAllowed, this._lastActiveWorkspace, this._variableResolver); + return terminalEnvironment.getDefaultShellArgs(fetchSetting, this._isWorkspaceShellAllowed, this._lastActiveWorkspace, this._variableResolver, this._logService); } public async resolveTerminalRenderer(id: number): Promise { diff --git a/src/vs/workbench/browser/parts/titlebar/menubarControl.ts b/src/vs/workbench/browser/parts/titlebar/menubarControl.ts index 66ae02ae0f..93cb19474d 100644 --- a/src/vs/workbench/browser/parts/titlebar/menubarControl.ts +++ b/src/vs/workbench/browser/parts/titlebar/menubarControl.ts @@ -587,7 +587,7 @@ export class CustomMenubarControl extends MenubarControl { this.updateService.checkForUpdates({ windowId })); case StateType.CheckingForUpdates: - return new Action('update.checking', nls.localize('checkingForUpdates', "Checking For Updates..."), undefined, false); + return new Action('update.checking', nls.localize('checkingForUpdates', "Checking for Updates..."), undefined, false); case StateType.AvailableForDownload: return new Action('update.downloadNow', nls.localize({ key: 'download now', comment: ['&& denotes a mnemonic'] }, "D&&ownload Now"), undefined, true, () => diff --git a/src/vs/workbench/browser/parts/views/customView.ts b/src/vs/workbench/browser/parts/views/customView.ts index c9a40011a8..6ca9d732a2 100644 --- a/src/vs/workbench/browser/parts/views/customView.ts +++ b/src/vs/workbench/browser/parts/views/customView.ts @@ -76,8 +76,8 @@ export class CustomTreeViewPanel extends ViewletPanel { this.treeView.show(container); } - layoutBody(size: number): void { - this.treeView.layout(size); + layoutBody(height: number, width: number): void { + this.treeView.layout(height, width); } getActions(): IAction[] { @@ -329,11 +329,11 @@ export class CustomTreeView extends Disposable implements ITreeView { this._onDidChangeVisibility.fire(this.isVisible); } - focus(): void { + focus(reveal: boolean = true): void { if (this.tree && this.root.children && this.root.children.length > 0) { // Make sure the current selected element is revealed const selectedElement = this.tree.getSelection()[0]; - if (selectedElement) { + if (selectedElement && reveal) { this.tree.reveal(selectedElement, 0.5); } @@ -384,7 +384,8 @@ export class CustomTreeView extends Disposable implements ITreeView { expandOnlyOnTwistieClick: (e: ITreeItem) => !!e.command, collapseByDefault: (e: ITreeItem): boolean => { return e.collapsibleState !== TreeItemCollapsibleState.Expanded; - } + }, + multipleSelectionSupport: false })); aligner.tree = this.tree; @@ -480,14 +481,14 @@ export class CustomTreeView extends Disposable implements ITreeView { this.markdownResult = this.markdownRenderer.render(this._messageValue); DOM.append(this.messageElement, this.markdownResult.element); } - this.layout(this._size); + this.layout(this._height, this._width); } } private hideMessage(): void { this.resetMessageElement(); DOM.addClass(this.messageElement, 'hide'); - this.layout(this._size); + this.layout(this._height, this._width); } private resetMessageElement(): void { @@ -498,14 +499,16 @@ export class CustomTreeView extends Disposable implements ITreeView { DOM.clearNode(this.messageElement); } - private _size: number; - layout(size: number) { - if (size) { - this._size = size; - const treeSize = size - DOM.getTotalHeight(this.messageElement); - this.treeContainer.style.height = treeSize + 'px'; + private _height: number; + private _width: number; + layout(height: number, width: number) { + if (height && width) { + this._height = height; + this._width = width; + const treeHeight = height - DOM.getTotalHeight(this.messageElement); + this.treeContainer.style.height = treeHeight + 'px'; if (this.tree) { - this.tree.layout(treeSize); + this.tree.layout(treeHeight, width); } } } @@ -595,10 +598,11 @@ export class CustomTreeView extends Disposable implements ITreeView { if (this.tree) { this.refreshing = true; await Promise.all(elements.map(element => this.tree.updateChildren(element, true))); + elements.map(element => this.tree.rerender(element)); this.refreshing = false; this.updateContentAreas(); if (this.focused) { - this.focus(); + this.focus(false); } } } diff --git a/src/vs/workbench/browser/parts/views/media/views.css b/src/vs/workbench/browser/parts/views/media/views.css index e01c715bd9..40214d63fb 100644 --- a/src/vs/workbench/browser/parts/views/media/views.css +++ b/src/vs/workbench/browser/parts/views/media/views.css @@ -104,6 +104,7 @@ .customview-tree .monaco-list .monaco-list-row { padding-right: 12px; + padding-left: 0px; } .customview-tree .monaco-list .monaco-list-row .custom-view-tree-node-item { diff --git a/src/vs/workbench/browser/parts/views/views.ts b/src/vs/workbench/browser/parts/views/views.ts index 8ad7955978..684b4b01ad 100644 --- a/src/vs/workbench/browser/parts/views/views.ts +++ b/src/vs/workbench/browser/parts/views/views.ts @@ -556,7 +556,8 @@ export class PersistentContributableViewsModel extends ContributableViewsModel { visibleGlobal: undefined, visibleWorkspace: isUndefined(workspaceViewState.isHidden) ? undefined : !workspaceViewState.isHidden, collapsed: workspaceViewState.collapsed, - order: workspaceViewState.order + order: workspaceViewState.order, + size: workspaceViewState.size }); } diff --git a/src/vs/workbench/browser/web.main.ts b/src/vs/workbench/browser/web.main.ts index 1867647028..5c34d323f1 100644 --- a/src/vs/workbench/browser/web.main.ts +++ b/src/vs/workbench/browser/web.main.ts @@ -118,7 +118,8 @@ class CodeRendererMain extends Disposable { const environmentService = new BrowserWorkbenchEnvironmentService({ workspaceId: payload.id, remoteAuthority: this.configuration.remoteAuthority, - webviewEndpoint: this.configuration.webviewEndpoint + webviewEndpoint: this.configuration.webviewEndpoint, + connectionToken: this.configuration.connectionToken }); serviceCollection.set(IWorkbenchEnvironmentService, environmentService); @@ -131,7 +132,7 @@ class CodeRendererMain extends Disposable { serviceCollection.set(IRemoteAuthorityResolverService, remoteAuthorityResolverService); // Signing - const signService = new SignService(this.configuration.connectionToken); + const signService = new SignService(environmentService.configuration.connectionToken); serviceCollection.set(ISignService, signService); // Remote Agent diff --git a/src/vs/workbench/browser/web.simpleservices.ts b/src/vs/workbench/browser/web.simpleservices.ts index 6a79a32cbe..d6bbc810ab 100644 --- a/src/vs/workbench/browser/web.simpleservices.ts +++ b/src/vs/workbench/browser/web.simpleservices.ts @@ -37,6 +37,7 @@ import { IRemoteAgentService } from 'vs/workbench/services/remote/common/remoteA // tslint:disable-next-line: import-patterns import { IExperimentService, IExperiment, ExperimentActionType, ExperimentState } from 'vs/workbench/contrib/experiments/common/experimentService'; import { ExtensionHostDebugChannelClient, ExtensionHostDebugBroadcastChannel } from 'vs/platform/debug/common/extensionHostDebugIpc'; +import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService'; //#region Extension Tips @@ -303,7 +304,8 @@ export class SimpleWindowService extends Disposable implements IWindowService { @IConfigurationService private readonly configurationService: IConfigurationService, @IStorageService private readonly storageService: IStorageService, @IWorkspaceContextService private readonly workspaceService: IWorkspaceContextService, - @ILogService private readonly logService: ILogService + @ILogService private readonly logService: ILogService, + @IWorkbenchEnvironmentService private readonly workbenchEnvironmentService: IWorkbenchEnvironmentService ) { super(); @@ -499,7 +501,7 @@ export class SimpleWindowService extends Disposable implements IWindowService { for (let i = 0; i < _uris.length; i++) { const uri = _uris[i]; if ('folderUri' in uri) { - const newAddress = `${document.location.origin}/?folder=${uri.folderUri.path}`; + const newAddress = `${document.location.origin}/?folder=${uri.folderUri.path}${this.workbenchEnvironmentService.configuration.connectionToken ? `&tkn=${this.workbenchEnvironmentService.configuration.connectionToken}` : ''}`; if (openFolderInNewWindow) { window.open(newAddress); } else { @@ -618,6 +620,10 @@ export class SimpleWindowsService implements IWindowsService { readonly onWindowUnmaximize: Event = Event.None; readonly onRecentlyOpenedChange: Event = Event.None; + constructor( + @IWorkbenchEnvironmentService private readonly workbenchEnvironmentService: IWorkbenchEnvironmentService + ) { + } isFocused(_windowId: number): Promise { return Promise.resolve(true); } @@ -788,6 +794,9 @@ export class SimpleWindowsService implements IWindowsService { newAddress += `&ibe=${encodeURIComponent(ibe)}`; } + // add connection token + newAddress += `${this.workbenchEnvironmentService.configuration.connectionToken ? `tkn=${this.workbenchEnvironmentService.configuration.connectionToken}` : ''}`; + window.open(newAddress); return Promise.resolve(); diff --git a/src/vs/workbench/browser/workbench.contribution.ts b/src/vs/workbench/browser/workbench.contribution.ts index b395ea6077..e665fae9e8 100644 --- a/src/vs/workbench/browser/workbench.contribution.ts +++ b/src/vs/workbench/browser/workbench.contribution.ts @@ -237,7 +237,7 @@ import { isMacintosh, isWindows, isLinux, isWeb } from 'vs/base/common/platform' 'workbench.useExperimentalGridLayout': { 'type': 'boolean', 'description': nls.localize('workbench.useExperimentalGridLayout', "Enables the grid layout for the workbench. This setting may enable additional layout options for workbench components."), - 'default': true, + 'default': false, 'scope': ConfigurationScope.APPLICATION } } @@ -360,4 +360,4 @@ import { isMacintosh, isWindows, isLinux, isWeb } from 'vs/base/common/platform' } } }); -})(); \ No newline at end of file +})(); diff --git a/src/vs/workbench/browser/workbench.ts b/src/vs/workbench/browser/workbench.ts index 499e18c8d4..16dc47a3e2 100644 --- a/src/vs/workbench/browser/workbench.ts +++ b/src/vs/workbench/browser/workbench.ts @@ -79,11 +79,25 @@ export class Workbench extends Layout { setUnexpectedErrorHandler(error => this.handleUnexpectedError(error, logService)); // Inform user about loading issues from the loader + interface AnnotatedLoadingError extends Error { + phase: 'loading'; + moduleId: string; + neededBy: string[]; + } + interface AnnotatedFactoryError extends Error { + phase: 'factory'; + moduleId: string; + } + interface AnnotatedValidationError extends Error { + phase: 'configuration'; + } + type AnnotatedError = AnnotatedLoadingError | AnnotatedFactoryError | AnnotatedValidationError; (window).require.config({ - onError: (err: { errorCode: string; }) => { - if (err.errorCode === 'load') { + onError: (err: AnnotatedError) => { + if (err.phase === 'loading') { onUnexpectedError(new Error(localize('loaderErrorNative', "Failed to load a required file. Please restart the application to try again. Details: {0}", JSON.stringify(err)))); } + console.error(err); } }); } diff --git a/src/vs/workbench/common/views.ts b/src/vs/workbench/common/views.ts index a95e6589fb..afeb6b2e0b 100644 --- a/src/vs/workbench/common/views.ts +++ b/src/vs/workbench/common/views.ts @@ -325,7 +325,7 @@ export interface ITreeView extends IDisposable { focus(): void; - layout(height: number): void; + layout(height: number, width: number): void; show(container: HTMLElement): void; diff --git a/src/vs/workbench/contrib/comments/browser/commentsEditorContribution.ts b/src/vs/workbench/contrib/comments/browser/commentsEditorContribution.ts index 0accf94141..6f81c1c882 100644 --- a/src/vs/workbench/contrib/comments/browser/commentsEditorContribution.ts +++ b/src/vs/workbench/contrib/comments/browser/commentsEditorContribution.ts @@ -36,6 +36,7 @@ import { ICommentInfo, ICommentService } from 'vs/workbench/contrib/comments/bro import { COMMENTEDITOR_DECORATION_KEY, ReviewZoneWidget } from 'vs/workbench/contrib/comments/browser/commentThreadWidget'; import { ctxCommentEditorFocused, SimpleCommentEditor } from 'vs/workbench/contrib/comments/browser/simpleCommentEditor'; import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; +import { EmbeddedCodeEditorWidget } from 'vs/editor/browser/widget/embeddedCodeEditorWidget'; export const ID = 'editor.contrib.review'; @@ -173,7 +174,6 @@ export class ReviewController implements IEditorContribution { @IContextMenuService readonly contextMenuService: IContextMenuService, @IQuickInputService private readonly quickInputService: IQuickInputService ) { - this.editor = editor; this.globalToDispose = []; this.localToDispose = []; this._commentInfos = []; @@ -181,6 +181,12 @@ export class ReviewController implements IEditorContribution { this._pendingCommentCache = {}; this._computePromise = null; + if (editor instanceof EmbeddedCodeEditorWidget) { + return; + } + + this.editor = editor; + this._commentingRangeDecorator = new CommentingRangeDecorator(); this.globalToDispose.push(this.commentService.onDidDeleteDataProvider(ownerId => { diff --git a/src/vs/workbench/contrib/comments/browser/media/review.css b/src/vs/workbench/contrib/comments/browser/media/review.css index b266e41cf9..9af91c0648 100644 --- a/src/vs/workbench/contrib/comments/browser/media/review.css +++ b/src/vs/workbench/contrib/comments/browser/media/review.css @@ -433,6 +433,10 @@ z-index: 10; } +div.preview.inline .monaco-editor .comment-range-glyph { + display: none !important; +} + .monaco-editor .comment-range-glyph:before { position: absolute; content: ""; diff --git a/src/vs/workbench/contrib/debug/browser/debugCommands.ts b/src/vs/workbench/contrib/debug/browser/debugCommands.ts index 3c600ec756..f317cf7f45 100644 --- a/src/vs/workbench/contrib/debug/browser/debugCommands.ts +++ b/src/vs/workbench/contrib/debug/browser/debugCommands.ts @@ -184,7 +184,7 @@ export function registerCommands(): void { id: STEP_INTO_ID, weight: KeybindingWeight.WorkbenchContrib + 10, // Have a stronger weight to have priority over full screen when debugging primary: KeyCode.F11, - when: CONTEXT_DEBUG_STATE.isEqualTo('stopped'), + when: CONTEXT_IN_DEBUG_MODE, handler: (accessor: ServicesAccessor, _: string, thread: IThread | undefined) => { getThreadAndRun(accessor, thread, thread => thread.stepIn()); } diff --git a/src/vs/workbench/contrib/extensions/browser/extensionsActions.ts b/src/vs/workbench/contrib/extensions/browser/extensionsActions.ts index dd0a3cd283..71707992e3 100644 --- a/src/vs/workbench/contrib/extensions/browser/extensionsActions.ts +++ b/src/vs/workbench/contrib/extensions/browser/extensionsActions.ts @@ -358,7 +358,7 @@ export class RemoteInstallAction extends InstallInOtherServerAction { } protected getInstallLabel(): string { - return this.extensionManagementServerService.remoteExtensionManagementServer ? localize('Install on Server', "Install on {0}", this.extensionManagementServerService.remoteExtensionManagementServer.label) : InstallInOtherServerAction.INSTALL_LABEL; + return this.extensionManagementServerService.remoteExtensionManagementServer ? localize('Install on Server', "Install in {0}", this.extensionManagementServerService.remoteExtensionManagementServer.label) : InstallInOtherServerAction.INSTALL_LABEL; } } @@ -712,7 +712,13 @@ export class ManageExtensionAction extends ExtensionDropDownAction { ]); groups.push([this.instantiationService.createInstance(UninstallAction)]); groups.push([this.instantiationService.createInstance(InstallAnotherVersionAction)]); - groups.push([this.instantiationService.createInstance(ExtensionInfoAction), this.instantiationService.createInstance(ExtensionSettingsAction)]); + + const extensionActions: ExtensionAction[] = [this.instantiationService.createInstance(ExtensionInfoAction)]; + if (this.extension.local && this.extension.local.manifest.contributes && this.extension.local.manifest.contributes.configuration) { + extensionActions.push(this.instantiationService.createInstance(ExtensionSettingsAction)); + } + + groups.push(extensionActions); groups.forEach(group => group.forEach(extensionAction => extensionAction.extension = this.extension)); @@ -3089,7 +3095,7 @@ interface IExtensionPickItem extends IQuickPickItem { extension?: IExtension; } -export class InstallLocalExtensionsOnRemoteAction extends Action { +export class InstallLocalExtensionsInRemoteAction extends Action { constructor( @IExtensionsWorkbenchService private readonly extensionsWorkbenchService: IExtensionsWorkbenchService, @@ -3101,14 +3107,14 @@ export class InstallLocalExtensionsOnRemoteAction extends Action { @IProgressService private readonly progressService: IProgressService, @IInstantiationService private readonly instantiationService: IInstantiationService ) { - super('workbench.extensions.actions.installLocalExtensionsOnRemote'); + super('workbench.extensions.actions.installLocalExtensionsInRemote'); this.update(); this._register(this.extensionsWorkbenchService.onChange(() => this.update())); } get label(): string { return this.extensionManagementServerService.remoteExtensionManagementServer ? - localize('install local extensions', "Install Local Extensions on {0}", this.extensionManagementServerService.remoteExtensionManagementServer.label) : ''; + localize('install local extensions', "Install Local Extensions in {0}...", this.extensionManagementServerService.remoteExtensionManagementServer.label) : ''; } private update(): void { @@ -3141,6 +3147,7 @@ export class InstallLocalExtensionsOnRemoteAction extends Action { const localExtensionsToInstall = this.getLocalExtensionsToInstall(); quickPick.busy = false; if (localExtensionsToInstall.length) { + quickPick.title = localize('install local extensions title', "Install Local Extensions in {0}", this.extensionManagementServerService.remoteExtensionManagementServer!.label); quickPick.placeholder = localize('select extensions to install', "Select extensions to install"); quickPick.canSelectMany = true; localExtensionsToInstall.sort((e1, e2) => e1.displayName.localeCompare(e2.displayName)); @@ -3189,9 +3196,9 @@ export class InstallLocalExtensionsOnRemoteAction extends Action { this.notificationService.notify({ severity: Severity.Info, - message: localize('finished installing', "Completed installing the extensions. Please reload the window now."), + message: localize('finished installing', "Successfully installed extensions in {0}. Please reload the window to enable them.", this.extensionManagementServerService.remoteExtensionManagementServer!.label), actions: { - primary: [new Action('realod', localize('reload', "Realod Window"), '', true, + primary: [new Action('realod', localize('reload', "Reload Window"), '', true, () => this.windowService.reloadWindow())] } }); diff --git a/src/vs/workbench/contrib/extensions/browser/extensionsDependencyChecker.ts b/src/vs/workbench/contrib/extensions/browser/extensionsDependencyChecker.ts index 142a5bb841..87afbb5054 100644 --- a/src/vs/workbench/contrib/extensions/browser/extensionsDependencyChecker.ts +++ b/src/vs/workbench/contrib/extensions/browser/extensionsDependencyChecker.ts @@ -68,7 +68,7 @@ export class ExtensionDependencyChecker extends Disposable implements IWorkbench severity: Severity.Info, message: localize('finished installing missing deps', "Finished installing missing dependencies. Please reload the window now."), actions: { - primary: [new Action('realod', localize('reload', "Realod Window"), '', true, + primary: [new Action('realod', localize('reload', "Reload Window"), '', true, () => this.windowService.reloadWindow())] } }); diff --git a/src/vs/workbench/contrib/extensions/browser/extensionsViewlet.ts b/src/vs/workbench/contrib/extensions/browser/extensionsViewlet.ts index 22efa0da26..1db4bd5db8 100644 --- a/src/vs/workbench/contrib/extensions/browser/extensionsViewlet.ts +++ b/src/vs/workbench/contrib/extensions/browser/extensionsViewlet.ts @@ -22,7 +22,7 @@ import { IExtensionsWorkbenchService, IExtensionsViewlet, VIEWLET_ID, AutoUpdate import { ShowEnabledExtensionsAction, ShowInstalledExtensionsAction, ShowRecommendedExtensionsAction, ShowPopularExtensionsAction, ShowDisabledExtensionsAction, ShowOutdatedExtensionsAction, ClearExtensionsInputAction, ChangeSortAction, UpdateAllAction, CheckForUpdatesAction, DisableAllAction, EnableAllAction, - EnableAutoUpdateAction, DisableAutoUpdateAction, ShowBuiltInExtensionsAction, InstallVSIXAction, InstallLocalExtensionsOnRemoteAction + EnableAutoUpdateAction, DisableAutoUpdateAction, ShowBuiltInExtensionsAction, InstallVSIXAction, InstallLocalExtensionsInRemoteAction } from 'vs/workbench/contrib/extensions/browser/extensionsActions'; import { IExtensionManagementService } from 'vs/platform/extensionManagement/common/extensionManagement'; import { IExtensionEnablementService, IExtensionManagementServerService, IExtensionManagementServer } from 'vs/workbench/services/extensionManagement/common/extensionManagement'; @@ -409,7 +409,7 @@ export class ExtensionsViewlet extends ViewContainerViewlet implements IExtensio triggerCharacters: ['@'], sortKey: (item: string) => { if (item.indexOf(':') === -1) { return 'a'; } - else if (/ext:/.test(item) || /tag:/.test(item)) { return 'b'; } + else if (/ext:/.test(item) || /id:/.test(item) || /tag:/.test(item)) { return 'b'; } else if (/sort:/.test(item)) { return 'c'; } else { return 'd'; } }, @@ -484,7 +484,7 @@ export class ExtensionsViewlet extends ViewContainerViewlet implements IExtensio this.instantiationService.createInstance(CheckForUpdatesAction, CheckForUpdatesAction.ID, CheckForUpdatesAction.LABEL), ...(this.configurationService.getValue(AutoUpdateConfigurationKey) ? [this.instantiationService.createInstance(DisableAutoUpdateAction, DisableAutoUpdateAction.ID, DisableAutoUpdateAction.LABEL)] : [this.instantiationService.createInstance(UpdateAllAction, UpdateAllAction.ID, UpdateAllAction.LABEL), this.instantiationService.createInstance(EnableAutoUpdateAction, EnableAutoUpdateAction.ID, EnableAutoUpdateAction.LABEL)]), this.instantiationService.createInstance(InstallVSIXAction, InstallVSIXAction.ID, InstallVSIXAction.LABEL), - ...(this.extensionManagementServerService.localExtensionManagementServer && this.extensionManagementServerService.remoteExtensionManagementServer ? [this.instantiationService.createInstance(InstallLocalExtensionsOnRemoteAction)] : []), + ...(this.extensionManagementServerService.localExtensionManagementServer && this.extensionManagementServerService.remoteExtensionManagementServer ? [this.instantiationService.createInstance(InstallLocalExtensionsInRemoteAction)] : []), new Separator(), this.instantiationService.createInstance(DisableAllAction, DisableAllAction.ID, DisableAllAction.LABEL), this.instantiationService.createInstance(EnableAllAction, EnableAllAction.ID, EnableAllAction.LABEL) diff --git a/src/vs/workbench/contrib/extensions/browser/media/profile-start-dark.svg b/src/vs/workbench/contrib/extensions/browser/media/profile-start-dark.svg index c67e550c15..a60d77cd37 100644 --- a/src/vs/workbench/contrib/extensions/browser/media/profile-start-dark.svg +++ b/src/vs/workbench/contrib/extensions/browser/media/profile-start-dark.svg @@ -1,10 +1,4 @@ - - - - - - - - + + diff --git a/src/vs/workbench/contrib/extensions/browser/media/profile-start-light.svg b/src/vs/workbench/contrib/extensions/browser/media/profile-start-light.svg index c67e550c15..f541ed4d51 100644 --- a/src/vs/workbench/contrib/extensions/browser/media/profile-start-light.svg +++ b/src/vs/workbench/contrib/extensions/browser/media/profile-start-light.svg @@ -1,10 +1,4 @@ - - - - - - - - + + diff --git a/src/vs/workbench/contrib/extensions/browser/media/start-dark.svg b/src/vs/workbench/contrib/extensions/browser/media/start-dark.svg index 9debdf8c62..8b0a58eca9 100644 --- a/src/vs/workbench/contrib/extensions/browser/media/start-dark.svg +++ b/src/vs/workbench/contrib/extensions/browser/media/start-dark.svg @@ -1,3 +1,3 @@ - + diff --git a/src/vs/workbench/contrib/extensions/browser/media/start-light.svg b/src/vs/workbench/contrib/extensions/browser/media/start-light.svg index dac8bdae31..2563bfa114 100644 --- a/src/vs/workbench/contrib/extensions/browser/media/start-light.svg +++ b/src/vs/workbench/contrib/extensions/browser/media/start-light.svg @@ -1,3 +1,3 @@ - + diff --git a/src/vs/workbench/contrib/extensions/browser/remoteExtensionsInstaller.ts b/src/vs/workbench/contrib/extensions/browser/remoteExtensionsInstaller.ts index b6e4edf9ba..44595ecaf9 100644 --- a/src/vs/workbench/contrib/extensions/browser/remoteExtensionsInstaller.ts +++ b/src/vs/workbench/contrib/extensions/browser/remoteExtensionsInstaller.ts @@ -11,7 +11,7 @@ import { Disposable, toDisposable } from 'vs/base/common/lifecycle'; import { IExtensionManagementServerService } from 'vs/workbench/services/extensionManagement/common/extensionManagement'; import { ILabelService } from 'vs/platform/label/common/label'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; -import { InstallLocalExtensionsOnRemoteAction } from 'vs/workbench/contrib/extensions/browser/extensionsActions'; +import { InstallLocalExtensionsInRemoteAction } from 'vs/workbench/contrib/extensions/browser/extensionsActions'; export class RemoteExtensionsInstaller extends Disposable implements IWorkbenchContribution { @@ -22,16 +22,16 @@ export class RemoteExtensionsInstaller extends Disposable implements IWorkbenchC ) { super(); if (this.extensionManagementServerService.localExtensionManagementServer && this.extensionManagementServerService.remoteExtensionManagementServer) { - const installLocalExtensionsOnRemoteAction = instantiationService.createInstance(InstallLocalExtensionsOnRemoteAction); - CommandsRegistry.registerCommand('workbench.extensions.installLocalExtensions', () => installLocalExtensionsOnRemoteAction.run()); + const installLocalExtensionsInRemoteAction = instantiationService.createInstance(InstallLocalExtensionsInRemoteAction); + CommandsRegistry.registerCommand('workbench.extensions.installLocalExtensions', () => installLocalExtensionsInRemoteAction.run()); let disposable = Disposable.None; const appendMenuItem = () => { disposable.dispose(); disposable = MenuRegistry.appendMenuItem(MenuId.CommandPalette, { command: { id: 'workbench.extensions.installLocalExtensions', - category: localize('extensions', "Extensions"), - title: installLocalExtensionsOnRemoteAction.label + category: localize('remote', "Remote"), + title: installLocalExtensionsInRemoteAction.label } }); }; @@ -41,4 +41,4 @@ export class RemoteExtensionsInstaller extends Disposable implements IWorkbenchC } } -} \ No newline at end of file +} diff --git a/src/vs/workbench/contrib/extensions/test/electron-browser/extensionsActions.test.ts b/src/vs/workbench/contrib/extensions/test/electron-browser/extensionsActions.test.ts index 70f2c1b6f8..b07bcb735a 100644 --- a/src/vs/workbench/contrib/extensions/test/electron-browser/extensionsActions.test.ts +++ b/src/vs/workbench/contrib/extensions/test/electron-browser/extensionsActions.test.ts @@ -1518,7 +1518,7 @@ suite('ExtensionsActions Test', () => { await workbenchService.queryGallery(CancellationToken.None); testObject.extension = extensions[0]; assert.ok(testObject.enabled); - assert.equal('Install on remote', testObject.label); + assert.equal('Install in remote', testObject.label); assert.equal('extension-action prominent install', testObject.class); }); @@ -1544,7 +1544,7 @@ suite('ExtensionsActions Test', () => { await workbenchService.queryGallery(CancellationToken.None); testObject.extension = extensions[0]; assert.ok(testObject.enabled); - assert.equal('Install on remote', testObject.label); + assert.equal('Install in remote', testObject.label); assert.equal('extension-action prominent install', testObject.class); onInstallExtension.fire({ identifier: localWorkspaceExtension.identifier, gallery }); @@ -1577,7 +1577,7 @@ suite('ExtensionsActions Test', () => { await workbenchService.queryGallery(CancellationToken.None); testObject.extension = extensions[0]; assert.ok(testObject.enabled); - assert.equal('Install on remote', testObject.label); + assert.equal('Install in remote', testObject.label); assert.equal('extension-action prominent install', testObject.class); onInstallExtension.fire({ identifier: localWorkspaceExtension.identifier, gallery }); @@ -1608,7 +1608,7 @@ suite('ExtensionsActions Test', () => { await workbenchService.queryGallery(CancellationToken.None); testObject.extension = extensions[0]; assert.ok(testObject.enabled); - assert.equal('Install on remote', testObject.label); + assert.equal('Install in remote', testObject.label); assert.equal('extension-action prominent install', testObject.class); }); @@ -1704,7 +1704,7 @@ suite('ExtensionsActions Test', () => { await workbenchService.queryGallery(CancellationToken.None); testObject.extension = extensions[0]; assert.ok(testObject.enabled); - assert.equal('Install on remote', testObject.label); + assert.equal('Install in remote', testObject.label); uninstallEvent.fire(localWorkspaceExtension.identifier); assert.ok(!testObject.enabled); @@ -1825,7 +1825,7 @@ suite('ExtensionsActions Test', () => { await workbenchService.queryGallery(CancellationToken.None); testObject.extension = extensions[0]; assert.ok(testObject.enabled); - assert.equal('Install on remote', testObject.label); + assert.equal('Install in remote', testObject.label); assert.equal('extension-action prominent install', testObject.class); }); @@ -1848,7 +1848,7 @@ suite('ExtensionsActions Test', () => { await workbenchService.queryGallery(CancellationToken.None); testObject.extension = extensions[0]; assert.ok(testObject.enabled); - assert.equal('Install on remote', testObject.label); + assert.equal('Install in remote', testObject.label); uninstallEvent.fire(languagePackExtension.identifier); assert.ok(!testObject.enabled); diff --git a/src/vs/workbench/contrib/markers/browser/markersTreeViewer.ts b/src/vs/workbench/contrib/markers/browser/markersTreeViewer.ts index 76d5353604..031cbd1368 100644 --- a/src/vs/workbench/contrib/markers/browser/markersTreeViewer.ts +++ b/src/vs/workbench/contrib/markers/browser/markersTreeViewer.ts @@ -258,7 +258,7 @@ class MarkerWidget extends Disposable { })); this.icon = dom.append(parent, dom.$('')); this.multilineActionbar = this._register(new ActionBar(dom.append(parent, dom.$('.multiline-actions')))); - this.messageAndDetailsContainer = dom.append(parent, dom.$('.marker-message-details')); + this.messageAndDetailsContainer = dom.append(parent, dom.$('.marker-message-details-container')); } render(element: Marker, filterData: MarkerFilterData | undefined): void { @@ -312,33 +312,32 @@ class MarkerWidget extends Disposable { const viewState = this.markersViewModel.getViewModel(element); const multiline = !viewState || viewState.multiline; const lineMatches = filterData && filterData.lineMatches || []; - const messageContainer = dom.append(this.messageAndDetailsContainer, dom.$('.marker-message')); - dom.toggleClass(messageContainer, 'multiline', multiline); - let lastLineElement = messageContainer; + let lastLineElement: HTMLElement | undefined = undefined; for (let index = 0; index < (multiline ? lines.length : 1); index++) { - lastLineElement = dom.append(messageContainer, dom.$('.marker-message-line')); - const highlightedLabel = new HighlightedLabel(lastLineElement, false); - highlightedLabel.set(lines[index], lineMatches[index]); + lastLineElement = dom.append(this.messageAndDetailsContainer, dom.$('.marker-message-line')); + const messageElement = dom.append(lastLineElement, dom.$('.marker-message')); + const highlightedLabel = new HighlightedLabel(messageElement, false); + highlightedLabel.set(lines[index].length > 1000 ? `${lines[index].substring(0, 1000)}...` : lines[index], lineMatches[index]); if (lines[index] === '') { lastLineElement.style.height = `${VirtualDelegate.LINE_HEIGHT}px`; } } - this.renderDetails(marker, filterData, multiline ? lastLineElement : this.messageAndDetailsContainer); + this.renderDetails(marker, filterData, lastLineElement || dom.append(this.messageAndDetailsContainer, dom.$('.marker-message-line'))); } private renderDetails(marker: IMarker, filterData: MarkerFilterData | undefined, parent: HTMLElement): void { dom.addClass(parent, 'details-container'); - const sourceMatches = filterData && filterData.sourceMatches || []; - const codeMatches = filterData && filterData.codeMatches || []; - const source = new HighlightedLabel(dom.append(parent, dom.$('')), false); - source.set(marker.source, sourceMatches); - dom.toggleClass(source.element, 'marker-source', !!marker.source); + if (marker.source || marker.code) { + const source = new HighlightedLabel(dom.append(parent, dom.$('.marker-source')), false); + const sourceMatches = filterData && filterData.sourceMatches || []; + source.set(marker.source, sourceMatches); - const code = new HighlightedLabel(dom.append(parent, dom.$('')), false); - code.set(marker.code, codeMatches); - dom.toggleClass(code.element, 'marker-code', !!marker.code); + const code = new HighlightedLabel(dom.append(parent, dom.$('.marker-code')), false); + const codeMatches = filterData && filterData.codeMatches || []; + code.set(marker.code, codeMatches); + } const lnCol = dom.append(parent, dom.$('span.marker-line')); lnCol.textContent = Messages.MARKERS_PANEL_AT_LINE_COL_NUMBER(marker.startLineNumber, marker.startColumn); diff --git a/src/vs/workbench/contrib/markers/browser/media/markers.css b/src/vs/workbench/contrib/markers/browser/media/markers.css index 2811aaa2b4..286d893381 100644 --- a/src/vs/workbench/contrib/markers/browser/media/markers.css +++ b/src/vs/workbench/contrib/markers/browser/media/markers.css @@ -97,6 +97,7 @@ .markers-panel .markers-panel-container .tree-container .monaco-tl-contents { display: flex; line-height: 22px; + padding-right: 10px; } .hc-black .markers-panel .markers-panel-container .tree-container .monaco-tl-contents { @@ -112,23 +113,22 @@ margin-left: 10px; } -.markers-panel .markers-panel-container .tree-container .monaco-tl-contents .marker-message-details, -.markers-panel .markers-panel-container .tree-container .monaco-tl-contents .marker-message:not(.multiline) { - display: flex; +.markers-panel .markers-panel-container .tree-container .monaco-tl-contents .marker-message-details-container { + flex: 1; overflow: hidden; } -.markers-panel .markers-panel-container .tree-container .monaco-tl-contents .marker-message.multiline { - white-space: pre; - flex: 1; +.markers-panel .markers-panel-container .tree-container .monaco-tl-contents .marker-message-details-container > .marker-message-line { + overflow: hidden; } -.markers-panel .markers-panel-container .tree-container .monaco-tl-contents .marker-message:not(.multiline) .marker-message-line { +.markers-panel .markers-panel-container .tree-container .monaco-tl-contents .marker-message-details-container > .marker-message-line > .marker-message { overflow: hidden; text-overflow: ellipsis; + white-space: nowrap; } -.markers-panel .markers-panel-container .tree-container .monaco-tl-contents .marker-message .details-container { +.markers-panel .markers-panel-container .tree-container .monaco-tl-contents .marker-message-details-container > .marker-message-line.details-container { display: flex; } @@ -222,4 +222,4 @@ .markers-panel .monaco-tl-contents .multiline-actions .action-item.disabled, .markers-panel .monaco-tl-contents .actions .action-item.disabled { display: none; -} \ No newline at end of file +} diff --git a/src/vs/workbench/contrib/preferences/browser/media/settingsWidgets.css b/src/vs/workbench/contrib/preferences/browser/media/settingsWidgets.css index 4c129e65f2..b0c2321445 100644 --- a/src/vs/workbench/contrib/preferences/browser/media/settingsWidgets.css +++ b/src/vs/workbench/contrib/preferences/browser/media/settingsWidgets.css @@ -12,10 +12,29 @@ margin-left: 2px; } +/* Deal with overflow */ +.settings-editor > .settings-body > .settings-tree-container .setting-item.setting-item-list .setting-list-widget .setting-list-value, +.settings-editor > .settings-body > .settings-tree-container .setting-item.setting-item-list .setting-list-widget .setting-list-sibling { + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} +.settings-editor > .settings-body > .settings-tree-container .setting-item.setting-item-list .setting-list-widget .setting-list-value { + max-width: 90%; +} +.settings-editor > .settings-body > .settings-tree-container .setting-item.setting-item-list .setting-list-widget .setting-list-sibling { + max-width: 10%; +} + .settings-editor > .settings-body > .settings-tree-container .setting-item.setting-item-list .setting-list-value, .settings-editor > .settings-body > .settings-tree-container .setting-item.setting-item-list .setting-list-sibling { display: inline-block; line-height: 22px; +} + +/* Use monospace to display glob patterns in exclude widget */ +.settings-editor > .settings-body > .settings-tree-container .setting-item.setting-item-list .setting-list-exclude-widget .setting-list-value, +.settings-editor > .settings-body > .settings-tree-container .setting-item.setting-item-list .setting-list-exclude-widget .setting-list-sibling { font-family: var(--monaco-monospace-font); } @@ -35,6 +54,7 @@ .settings-editor > .settings-body > .settings-tree-container .setting-item.setting-item-list .setting-list-row { position: relative; + max-height: 22px; } .settings-editor > .settings-body > .settings-tree-container .setting-item.setting-item-list .setting-list-row:focus { @@ -102,6 +122,8 @@ margin-right: 10px; } -.settings-editor > .settings-body > .settings-tree-container .setting-item.setting-item-list .setting-list-widget { +.settings-editor > .settings-body > .settings-tree-container .setting-item.setting-item-list .setting-list-widget, +.settings-editor > .settings-body > .settings-tree-container .setting-item.setting-item-list .setting-list-exclude-widget { margin-bottom: 1px; + padding: 1px; } diff --git a/src/vs/workbench/contrib/preferences/browser/settingsEditor2.ts b/src/vs/workbench/contrib/preferences/browser/settingsEditor2.ts index 269a6c97ac..9cfcb7f0cc 100644 --- a/src/vs/workbench/contrib/preferences/browser/settingsEditor2.ts +++ b/src/vs/workbench/contrib/preferences/browser/settingsEditor2.ts @@ -978,8 +978,15 @@ export class SettingsEditor2 extends BaseEditor { // If a single setting is being refreshed, it's ok to refresh now if that is not the focused setting if (key) { const focusedKey = focusedSetting.getAttribute(AbstractSettingRenderer.SETTING_KEY_ATTR); - if (focusedKey === key && - !DOM.hasClass(focusedSetting, 'setting-item-list')) { // update `list`s live, as they have a separate "submit edit" step built in before this + /** + * Update `list`s live if focused item is whole list or list item, + * as they have a separate "submit edit" step built in before this + */ + if ( + focusedKey === key && + !DOM.hasClass(focusedSetting, 'setting-item-list') && + !DOM.hasClass(focusedSetting, 'setting-item-contents') + ) { this.updateModifiedLabelForKey(key); this.scheduleRefresh(focusedSetting, key); diff --git a/src/vs/workbench/contrib/preferences/browser/settingsTree.ts b/src/vs/workbench/contrib/preferences/browser/settingsTree.ts index a91ee70fed..0e612186e0 100644 --- a/src/vs/workbench/contrib/preferences/browser/settingsTree.ts +++ b/src/vs/workbench/contrib/preferences/browser/settingsTree.ts @@ -698,32 +698,46 @@ export class SettingArrayRenderer extends AbstractSettingRenderer implements ITr private onDidChangeList(template: ISettingListItemTemplate, e: IListChangeEvent): void { if (template.context) { - const newValue: any[] | undefined = isArray(template.context.scopeValue) - ? [...template.context.scopeValue] - : [...template.context.value]; + let newValue: any[] = []; + if (isArray(template.context.scopeValue)) { + newValue = [...template.context.scopeValue]; + } else if (isArray(template.context.value)) { + newValue = [...template.context.value]; + } - // Delete value - if (e.removeIndex) { - if (!e.value && e.originalValue && e.removeIndex > -1) { - newValue.splice(e.removeIndex, 1); + if (e.targetIndex !== undefined) { + // Delete value + if (!e.value && e.originalValue && e.targetIndex > -1) { + newValue.splice(e.targetIndex, 1); } - } - // Add value - else if (e.value && !e.originalValue) { - newValue.push(e.value); - } - // Update value - else if (e.value && e.originalValue) { - const valueIndex = newValue.indexOf(e.originalValue); - if (valueIndex > -1) { - newValue[valueIndex] = e.value; + // Update value + else if (e.value && e.originalValue) { + if (e.targetIndex > -1) { + newValue[e.targetIndex] = e.value; + } + // For some reason, we are updating and cannot find original value + // Just append the value in this case + else { + newValue.push(e.value); + } } - // For some reason, we are updating and cannot find original value - // Just append the value in this case - else { + // Add value + else if (e.value && !e.originalValue && e.targetIndex >= newValue.length) { newValue.push(e.value); } } + if ( + template.context.defaultValue && + isArray(template.context.defaultValue) && + template.context.defaultValue.length === newValue.length && + template.context.defaultValue.join() === newValue.join() + ) { + return this._onDidChangeSetting.fire({ + key: template.context.setting.key, + value: undefined, // reset setting + type: template.context.valueType + }); + } this._onDidChangeSetting.fire({ key: template.context.setting.key, diff --git a/src/vs/workbench/contrib/preferences/browser/settingsWidgets.ts b/src/vs/workbench/contrib/preferences/browser/settingsWidgets.ts index 795aff8c2b..3d2a68bd8b 100644 --- a/src/vs/workbench/contrib/preferences/browser/settingsWidgets.ts +++ b/src/vs/workbench/contrib/preferences/browser/settingsWidgets.ts @@ -20,6 +20,7 @@ import { foreground, inputBackground, inputBorder, inputForeground, listActiveSe import { attachButtonStyler, attachInputBoxStyler } from 'vs/platform/theme/common/styler'; import { ICssStyleCollector, ITheme, IThemeService, registerThemingParticipant } from 'vs/platform/theme/common/themeService'; import { disposableTimeout } from 'vs/base/common/async'; +import { isUndefinedOrNull } from 'vs/base/common/types'; const $ = DOM.$; export const settingsHeaderForeground = registerColor('settings.headerForeground', { light: '#444444', dark: '#e7e7e7', hc: '#ffffff' }, localize('headerForeground', "(For settings editor preview) The foreground color for a section header or active title.")); @@ -131,14 +132,16 @@ registerThemingParticipant((theme: ITheme, collector: ICssStyleCollector) => { } }); +type EditKey = 'none' | 'create' | number; + export class ListSettingListModel { private _dataItems: IListDataItem[] = []; - private _editKey: string | null; + private _editKey: EditKey; private _selectedIdx: number | null; get items(): IListViewItem[] { const items = this._dataItems.map((item, i) => { - const editing = item.value === this._editKey; + const editing = typeof this._editKey === 'number' && this._editKey === i; return { ...item, editing, @@ -146,7 +149,7 @@ export class ListSettingListModel { }; }); - if (this._editKey === '') { + if (this._editKey === 'create') { items.push({ editing: true, selected: true, @@ -158,7 +161,7 @@ export class ListSettingListModel { return items; } - setEditKey(key: string | null): void { + setEditKey(key: EditKey): void { this._editKey = key; } @@ -195,7 +198,7 @@ export interface IListChangeEvent { originalValue: string; value?: string; sibling?: string; - removeIndex?: number; + targetIndex?: number; } export class ListSettingWidget extends Disposable { @@ -218,7 +221,8 @@ export class ListSettingWidget extends Disposable { ) { super(); - this.listElement = DOM.append(container, $('.setting-list-widget')); + this.listElement = DOM.append(container, $('div')); + this.getContainerClasses().forEach(c => this.listElement.classList.add(c)); this.listElement.setAttribute('tabindex', '0'); DOM.append(container, this.renderAddButton()); this.renderList(); @@ -228,13 +232,19 @@ export class ListSettingWidget extends Disposable { this._register(DOM.addStandardDisposableListener(this.listElement, 'keydown', (e: KeyboardEvent) => { if (e.keyCode === KeyCode.UpArrow) { + const selectedIndex = this.model.getSelected(); this.model.selectPrevious(); - this.renderList(); + if (this.model.getSelected() !== selectedIndex) { + this.renderList(); + } e.preventDefault(); e.stopPropagation(); } else if (e.keyCode === KeyCode.DownArrow) { + const selectedIndex = this.model.getSelected(); this.model.selectNext(); - this.renderList(); + if (this.model.getSelected() !== selectedIndex) { + this.renderList(); + } e.preventDefault(); e.stopPropagation(); } @@ -259,6 +269,10 @@ export class ListSettingWidget extends Disposable { }; } + protected getContainerClasses() { + return ['setting-list-widget']; + } + setValue(listData: IListDataItem[]): void { this.model.setValue(listData); this.renderList(); @@ -288,7 +302,7 @@ export class ListSettingWidget extends Disposable { const item = this.model.items[targetIdx]; if (item) { - this.editSetting(item.value); + this.editSetting(targetIdx); e.preventDefault(); e.stopPropagation(); } @@ -342,30 +356,30 @@ export class ListSettingWidget extends Disposable { enabled: true, id: 'workbench.action.removeListItem', tooltip: this.getLocalizedStrings().deleteActionTooltip, - run: () => this._onDidChangeList.fire({ originalValue: key, value: undefined, removeIndex: idx }) + run: () => this._onDidChangeList.fire({ originalValue: key, value: undefined, targetIndex: idx }) }; } - private createEditAction(key: string): IAction { + private createEditAction(idx: number): IAction { return { class: 'setting-listAction-edit', enabled: true, id: 'workbench.action.editListItem', tooltip: this.getLocalizedStrings().editActionTooltip, run: () => { - this.editSetting(key); + this.editSetting(idx); } }; } - private editSetting(key: string): void { - this.model.setEditKey(key); + private editSetting(idx: number): void { + this.model.setEditKey(idx); this.renderList(); } private renderItem(item: IListViewItem, idx: number, listFocused: boolean): HTMLElement { return item.editing ? - this.renderEditItem(item) : + this.renderEditItem(item, idx) : this.renderDataItem(item, idx, listFocused); } @@ -384,7 +398,7 @@ export class ListSettingWidget extends Disposable { siblingElement.textContent = item.sibling ? ('when: ' + item.sibling) : null; actionBar.push([ - this.createEditAction(item.value), + this.createEditAction(idx), this.createDeleteAction(item.value, idx) ], { icon: true, label: false }); @@ -412,24 +426,25 @@ export class ListSettingWidget extends Disposable { this._register(attachButtonStyler(startAddButton, this.themeService)); this._register(startAddButton.onDidClick(() => { - this.model.setEditKey(''); + this.model.setEditKey('create'); this.renderList(); })); return rowElement; } - private renderEditItem(item: IListViewItem): HTMLElement { + private renderEditItem(item: IListViewItem, idx: number): HTMLElement { const rowElement = $('.setting-list-edit-row'); const onSubmit = (edited: boolean) => { - this.model.setEditKey(null); + this.model.setEditKey('none'); const value = valueInput.value.trim(); - if (edited && value) { + if (edited && !isUndefinedOrNull(value)) { this._onDidChangeList.fire({ originalValue: item.value, value: value, - sibling: siblingInput && siblingInput.value.trim() + sibling: siblingInput && siblingInput.value.trim(), + targetIndex: idx }); } this.renderList(); @@ -514,6 +529,10 @@ export class ExcludeSettingWidget extends ListSettingWidget { settingListRowSiblingHintLabel: localize('excludeSiblingHintLabel', "Exclude files matching `{0}`, only when a file matching `{1}` is present", pattern, sibling) }; } + + protected getContainerClasses() { + return ['setting-list-exclude-widget']; + } } export interface IListDataItem { diff --git a/src/vs/workbench/contrib/remote/electron-browser/remote.contribution.ts b/src/vs/workbench/contrib/remote/electron-browser/remote.contribution.ts index 9eb3921a99..f5e16ee5d9 100644 --- a/src/vs/workbench/contrib/remote/electron-browser/remote.contribution.ts +++ b/src/vs/workbench/contrib/remote/electron-browser/remote.contribution.ts @@ -284,6 +284,26 @@ class ProgressReporter { } } +class RemoteExtensionHostEnvironmentUpdater implements IWorkbenchContribution { + constructor( + @IRemoteAgentService remoteAgentService: IRemoteAgentService, + @IRemoteAuthorityResolverService remoteResolverService: IRemoteAuthorityResolverService, + @IExtensionService extensionService: IExtensionService + ) { + const connection = remoteAgentService.getConnection(); + if (connection) { + connection.onDidStateChange(async e => { + if (e.type === PersistentConnectionEventType.ConnectionGain) { + const resolveResult = await remoteResolverService.resolveAuthority(connection.remoteAuthority); + if (resolveResult.options && resolveResult.options.extensionHostEnv) { + await extensionService.setRemoteEnvironment(resolveResult.options.extensionHostEnv); + } + } + }); + } + } +} + class RemoteAgentConnectionStatusListener implements IWorkbenchContribution { constructor( @IRemoteAgentService remoteAgentService: IRemoteAgentService, @@ -440,6 +460,7 @@ const workbenchContributionsRegistry = Registry.as { - const viewletService = accessor.get(IViewletService); - const explorerService = accessor.get(IExplorerService); - const contextService = accessor.get(IWorkspaceContextService); - const uri = fileMatch.resource; - - viewletService.openViewlet(VIEWLET_ID_FILES, false).then((viewlet: ExplorerViewlet) => { - if (uri && contextService.isInsideWorkspace(uri)) { - const explorerView = viewlet.getExplorerView(); - if (explorerView) { - explorerView.setExpanded(true); - explorerService.select(uri, true).then(() => explorerView.focus(), onUnexpectedError); - } - } - }); - } -}); - -const RevealInSideBarForSearchResultsCommand: ICommandAction = { - id: Constants.RevealInSideBarForSearchResults, - title: nls.localize('revealInSideBar', "Reveal in Explorer") -}; - -MenuRegistry.appendMenuItem(MenuId.SearchContext, { - command: RevealInSideBarForSearchResultsCommand, - when: ContextKeyExpr.and(Constants.FileFocusKey, Constants.HasSearchResults), - group: '2_files', -}); - MenuRegistry.appendMenuItem(MenuId.SearchContext, { command: { id: Constants.ReplaceActionId, @@ -343,6 +312,38 @@ CommandsRegistry.registerCommand({ handler: clearHistoryCommand }); +CommandsRegistry.registerCommand({ + id: Constants.RevealInSideBarForSearchResults, + handler: (accessor, fileMatch: FileMatch) => { + const viewletService = accessor.get(IViewletService); + const explorerService = accessor.get(IExplorerService); + const contextService = accessor.get(IWorkspaceContextService); + const uri = fileMatch.resource; + + viewletService.openViewlet(VIEWLET_ID_FILES, false).then((viewlet: ExplorerViewlet) => { + if (uri && contextService.isInsideWorkspace(uri)) { + const explorerView = viewlet.getExplorerView(); + if (explorerView) { + explorerView.setExpanded(true); + explorerService.select(uri, true).then(() => explorerView.focus(), onUnexpectedError); + } + } + }); + } +}); + +const RevealInSideBarForSearchResultsCommand: ICommandAction = { + id: Constants.RevealInSideBarForSearchResults, + title: nls.localize('revealInSideBar', "Reveal in Explorer") +}; + +MenuRegistry.appendMenuItem(MenuId.SearchContext, { + command: RevealInSideBarForSearchResultsCommand, + when: ContextKeyExpr.and(Constants.FileFocusKey, Constants.HasSearchResults), + group: 'search_3', + order: 1 +}); + const clearSearchHistoryLabel = nls.localize('clearSearchHistoryLabel', "Clear Search History"); const ClearSearchHistoryCommand: ICommandAction = { id: Constants.ClearSearchHistoryCommandId, diff --git a/src/vs/workbench/contrib/tasks/browser/abstractTaskService.ts b/src/vs/workbench/contrib/tasks/browser/abstractTaskService.ts index cf33ff57a6..0dd1c99c96 100644 --- a/src/vs/workbench/contrib/tasks/browser/abstractTaskService.ts +++ b/src/vs/workbench/contrib/tasks/browser/abstractTaskService.ts @@ -470,17 +470,7 @@ export abstract class AbstractTaskService extends Disposable implements ITaskSer return this._taskSystem.customExecutionComplete(task, result); } - private isBadTsConfig(taskId: string | TaskIdentifier | undefined): taskId is string { - const badTsconfig = '\\tsconfig.json'; - const tsc = 'tsc'; - return typeof taskId === 'string' && (taskId.length > badTsconfig.length) && strings.equalsIgnoreCase(taskId.substring(taskId.length - badTsconfig.length, taskId.length), badTsconfig) && (taskId.substring(0, tsc.length) === tsc); - } - public getTask(folder: IWorkspaceFolder | string, identifier: string | TaskIdentifier, compareId: boolean = false): Promise { - if (this.isBadTsConfig(identifier)) { - return Promise.reject(new Error(nls.localize('badTsConfig', "Task '{0}' contains \"\\\\\". Typescript tasks must use \"/\"", identifier))); - } - const name = Types.isString(folder) ? folder : folder.name; if (this.ignoredWorkspaceFolders.some(ignored => ignored.name === name)) { return Promise.reject(new Error(nls.localize('TaskServer.folderIgnored', 'The folder {0} is ignored since it uses task version 0.1.0', name))); diff --git a/src/vs/workbench/contrib/terminal/browser/terminal.contribution.ts b/src/vs/workbench/contrib/terminal/browser/terminal.contribution.ts index 4ba2d5beb1..4c37451867 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminal.contribution.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminal.contribution.ts @@ -378,6 +378,9 @@ actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(RenameTerminalAc actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(FocusTerminalFindWidgetAction, FocusTerminalFindWidgetAction.ID, FocusTerminalFindWidgetAction.LABEL, { primary: KeyMod.CtrlCmd | KeyCode.KEY_F }, KEYBINDING_CONTEXT_TERMINAL_FOCUS), 'Terminal: Focus Find Widget', category); +actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(FocusTerminalFindWidgetAction, FocusTerminalFindWidgetAction.ID, FocusTerminalFindWidgetAction.LABEL, { + primary: KeyMod.CtrlCmd | KeyCode.KEY_F +}, KEYBINDING_CONTEXT_TERMINAL_FIND_WIDGET_FOCUSED), 'Terminal: Focus Find Widget', category); actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(HideTerminalFindWidgetAction, HideTerminalFindWidgetAction.ID, HideTerminalFindWidgetAction.LABEL, { primary: KeyCode.Escape, secondary: [KeyMod.Shift | KeyCode.Escape] diff --git a/src/vs/workbench/contrib/terminal/browser/terminalLinkHandler.ts b/src/vs/workbench/contrib/terminal/browser/terminalLinkHandler.ts index cb03a355f9..6770bb336c 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalLinkHandler.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalLinkHandler.ts @@ -38,6 +38,7 @@ const winLocalLinkClause = '((' + winPathPrefix + '|(' + winExcludedPathCharacte replacing space with nonBreakningSpace or space ASCII code - 32. */ const lineAndColumnClause = [ '((\\S*)", line ((\\d+)( column (\\d+))?))', // "(file path)", line 45 [see #40468] + '((\\S*)",((\\d+)(:(\\d+))?))', // "(file path)",45 [see #78205] '((\\S*) on line ((\\d+)(, column (\\d+))?))', // (file path) on line 8, column 13 '((\\S*):line ((\\d+)(, column (\\d+))?))', // (file path):line 8, column 13 '(([^\\s\\(\\)]*)(\\s?[\\(\\[](\\d+)(,\\s?(\\d+))?)[\\)\\]])', // (file path)(45), (file path) (45), (file path)(45,18), (file path) (45,18), (file path)(45, 18), (file path) (45, 18), also with [] diff --git a/src/vs/workbench/contrib/terminal/common/terminalEnvironment.ts b/src/vs/workbench/contrib/terminal/common/terminalEnvironment.ts index 3f0ddd2756..3045d9aeba 100644 --- a/src/vs/workbench/contrib/terminal/common/terminalEnvironment.ts +++ b/src/vs/workbench/contrib/terminal/common/terminalEnvironment.ts @@ -78,7 +78,11 @@ function resolveConfigurationVariables(configurationResolverService: IConfigurat Object.keys(env).forEach((key) => { const value = env[key]; if (typeof value === 'string' && lastActiveWorkspaceRoot !== null) { - env[key] = configurationResolverService.resolve(lastActiveWorkspaceRoot, value); + try { + env[key] = configurationResolverService.resolve(lastActiveWorkspaceRoot, value); + } catch (e) { + env[key] = value; + } } }); return env; @@ -138,19 +142,19 @@ export function getCwd( if (!shell.ignoreConfigurationCwd && customCwd) { if (configurationResolverService) { try { - cwd = configurationResolverService.resolve(lastActiveWorkspace, customCwd); + customCwd = configurationResolverService.resolve(lastActiveWorkspace, customCwd); } catch (e) { // There was an issue resolving a variable, just use the unresolved customCwd which // which will fail, and log the error in the console. - cwd = customCwd; if (logService) { - logService.error('Resolving terminal.integrated.cwd', e); + logService.error('Could not resolve terminal.integrated.cwd', e); } + return customCwd; } } - if (path.isAbsolute(customCwd) && !cwd) { + if (path.isAbsolute(customCwd)) { cwd = customCwd; - } else if (root && !cwd) { + } else if (root) { cwd = path.join(root.fsPath, customCwd); } } @@ -192,7 +196,8 @@ export function getDefaultShell( windir: string | undefined, lastActiveWorkspace: IWorkspaceFolder | undefined, configurationResolverService: IConfigurationResolverService | undefined, - platformOverride: platform.Platform = platform.platform, + logService: ILogService, + platformOverride: platform.Platform = platform.platform ): string { const platformKey = platformOverride === platform.Platform.Windows ? 'windows' : platformOverride === platform.Platform.Mac ? 'osx' : 'linux'; const shellConfigValue = fetchSetting(`terminal.integrated.shell.${platformKey}`); @@ -214,7 +219,12 @@ export function getDefaultShell( } if (configurationResolverService) { - executable = configurationResolverService.resolve(lastActiveWorkspace, executable); + try { + executable = configurationResolverService.resolve(lastActiveWorkspace, executable); + } catch (e) { + logService.error(`Could not resolve terminal.integrated.shell.${platformKey}`, e); + executable = executable; + } } return executable; @@ -225,6 +235,7 @@ export function getDefaultShellArgs( isWorkspaceShellAllowed: boolean, lastActiveWorkspace: IWorkspaceFolder | undefined, configurationResolverService: IConfigurationResolverService | undefined, + logService: ILogService, platformOverride: platform.Platform = platform.platform, ): string | string[] { const platformKey = platformOverride === platform.Platform.Windows ? 'windows' : platformOverride === platform.Platform.Mac ? 'osx' : 'linux'; @@ -236,7 +247,12 @@ export function getDefaultShellArgs( if (configurationResolverService) { const resolvedArgs: string[] = []; for (const arg of args) { - resolvedArgs.push(configurationResolverService.resolve(lastActiveWorkspace, arg)); + try { + resolvedArgs.push(configurationResolverService.resolve(lastActiveWorkspace, arg)); + } catch (e) { + logService.error(`Could not resolve terminal.integrated.shellArgs.${platformKey}`, e); + resolvedArgs.push(arg); + } } args = resolvedArgs; } diff --git a/src/vs/workbench/contrib/terminal/electron-browser/terminalInstanceService.ts b/src/vs/workbench/contrib/terminal/electron-browser/terminalInstanceService.ts index 5e3bb6889b..e380d337f7 100644 --- a/src/vs/workbench/contrib/terminal/electron-browser/terminalInstanceService.ts +++ b/src/vs/workbench/contrib/terminal/electron-browser/terminalInstanceService.ts @@ -20,6 +20,7 @@ import { getMainProcessParentEnv } from 'vs/workbench/contrib/terminal/node/term import { IConfigurationResolverService } from 'vs/workbench/services/configurationResolver/common/configurationResolver'; import { IHistoryService } from 'vs/workbench/services/history/common/history'; import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; +import { ILogService } from 'vs/platform/log/common/log'; let Terminal: typeof XTermTerminal; let WebLinksAddon: typeof XTermWebLinksAddon; @@ -34,7 +35,8 @@ export class TerminalInstanceService implements ITerminalInstanceService { @IStorageService private readonly _storageService: IStorageService, @IConfigurationResolverService private readonly _configurationResolverService: IConfigurationResolverService, @IWorkspaceContextService private readonly _workspaceContextService: IWorkspaceContextService, - @IHistoryService private readonly _historyService: IHistoryService + @IHistoryService private readonly _historyService: IHistoryService, + @ILogService private readonly _logService: ILogService ) { } @@ -84,6 +86,7 @@ export class TerminalInstanceService implements ITerminalInstanceService { process.env.windir, lastActiveWorkspace, this._configurationResolverService, + this._logService, platformOverride ); const args = getDefaultShellArgs( @@ -91,6 +94,7 @@ export class TerminalInstanceService implements ITerminalInstanceService { isWorkspaceShellAllowed, lastActiveWorkspace, this._configurationResolverService, + this._logService, platformOverride ); return Promise.resolve({ shell, args }); @@ -99,4 +103,4 @@ export class TerminalInstanceService implements ITerminalInstanceService { public getMainProcessParentEnv(): Promise { return getMainProcessParentEnv(); } -} \ No newline at end of file +} diff --git a/src/vs/workbench/contrib/terminal/node/terminal.ts b/src/vs/workbench/contrib/terminal/node/terminal.ts index 4ffada309b..85397c1610 100644 --- a/src/vs/workbench/contrib/terminal/node/terminal.ts +++ b/src/vs/workbench/contrib/terminal/node/terminal.ts @@ -120,10 +120,11 @@ async function detectAvailableWindowsShells(): Promise { `${process.env['ProgramFiles']}\\Git\\usr\\bin\\bash.exe`, `${process.env['LocalAppData']}\\Programs\\Git\\bin\\bash.exe`, ], - Cygwin: [ - `${process.env['HOMEDRIVE']}\\cygwin64\\bin\\bash.exe`, - `${process.env['HOMEDRIVE']}\\cygwin\\bin\\bash.exe` - ] + // See #75945 + // Cygwin: [ + // `${process.env['HOMEDRIVE']}\\cygwin64\\bin\\bash.exe`, + // `${process.env['HOMEDRIVE']}\\cygwin\\bin\\bash.exe` + // ] }; const promises: PromiseLike[] = []; Object.keys(expectedLocations).forEach(key => promises.push(validateShellPaths(key, expectedLocations[key]))); @@ -170,4 +171,4 @@ async function getShellPathFromRegistry(shellName: string): Promise { } catch (error) { return ''; } -} \ No newline at end of file +} diff --git a/src/vs/workbench/contrib/terminal/test/electron-browser/terminalLinkHandler.test.ts b/src/vs/workbench/contrib/terminal/test/electron-browser/terminalLinkHandler.test.ts index 26087f7b17..23dd24db04 100644 --- a/src/vs/workbench/contrib/terminal/test/electron-browser/terminalLinkHandler.test.ts +++ b/src/vs/workbench/contrib/terminal/test/electron-browser/terminalLinkHandler.test.ts @@ -121,7 +121,8 @@ suite('Workbench - TerminalLinkHandler', () => { { urlFormat: '{0}[{1},{2}]', line: '5', column: '3' }, { urlFormat: '{0} [{1},{2}]', line: '5', column: '3' }, { urlFormat: '{0}[{1}, {2}]', line: '5', column: '3' }, - { urlFormat: '{0} [{1}, {2}]', line: '5', column: '3' } + { urlFormat: '{0} [{1}, {2}]', line: '5', column: '3' }, + { urlFormat: '"{0}",{1}', line: '5' } ]; linkUrls.forEach(linkUrl => { @@ -185,7 +186,8 @@ suite('Workbench - TerminalLinkHandler', () => { { urlFormat: '{0}[{1}]', line: '5' }, { urlFormat: '{0} [{1}]', line: '5' }, { urlFormat: '{0}[{1},{2}]', line: '5', column: '3' }, - { urlFormat: '{0} [{1},{2}]', line: '5', column: '3' } + { urlFormat: '{0} [{1},{2}]', line: '5', column: '3' }, + { urlFormat: '"{0}",{1}', line: '5' } ]; linkUrls.forEach(linkUrl => { diff --git a/src/vs/workbench/contrib/update/electron-browser/update.ts b/src/vs/workbench/contrib/update/electron-browser/update.ts index e2e91d8220..6cfefbf834 100644 --- a/src/vs/workbench/contrib/update/electron-browser/update.ts +++ b/src/vs/workbench/contrib/update/electron-browser/update.ts @@ -490,7 +490,7 @@ export class UpdateContribution extends Disposable implements IWorkbenchContribu group: '5_update', command: { id: 'update.checking', - title: nls.localize('checkingForUpdates', "Checking For Updates..."), + title: nls.localize('checkingForUpdates', "Checking for Updates..."), precondition: FalseContext }, when: CONTEXT_UPDATE_STATE.isEqualTo(StateType.CheckingForUpdates) diff --git a/src/vs/workbench/contrib/webview/common/themeing.ts b/src/vs/workbench/contrib/webview/common/themeing.ts index ec6a4d9190..990e2be3e6 100644 --- a/src/vs/workbench/contrib/webview/common/themeing.ts +++ b/src/vs/workbench/contrib/webview/common/themeing.ts @@ -31,7 +31,7 @@ export function getWebviewThemeData( }, {} as { [key: string]: string }); const styles = { - 'vscode-font-family': '-apple-system, BlinkMacSystemFont, "Segoe WPC", "Segoe UI", "Ubuntu", "Droid Sans", ans-serif', + 'vscode-font-family': '-apple-system, BlinkMacSystemFont, "Segoe WPC", "Segoe UI", "Ubuntu", "Droid Sans", sans-serif', 'vscode-font-weight': 'normal', 'vscode-font-size': '13px', 'vscode-editor-font-family': editorFontFamily, @@ -60,4 +60,4 @@ namespace ApiThemeClassName { return ApiThemeClassName.highContrast; } } -} \ No newline at end of file +} diff --git a/src/vs/workbench/services/environment/browser/environmentService.ts b/src/vs/workbench/services/environment/browser/environmentService.ts index 2ba5f192a8..a09a66a5ce 100644 --- a/src/vs/workbench/services/environment/browser/environmentService.ts +++ b/src/vs/workbench/services/environment/browser/environmentService.ts @@ -61,6 +61,7 @@ export interface IBrowserWindowConfiguration { workspaceId: string; remoteAuthority?: string; webviewEndpoint?: string; + connectionToken?: string; } export class BrowserWorkbenchEnvironmentService implements IEnvironmentService { @@ -81,6 +82,7 @@ export class BrowserWorkbenchEnvironmentService implements IEnvironmentService { this.localeResource = joinPath(this.userRoamingDataHome, 'locale.json'); this.backupHome = joinPath(this.userRoamingDataHome, BACKUPS); this.configuration.backupWorkspaceResource = joinPath(this.backupHome, configuration.workspaceId); + this.configuration.connectionToken = configuration.connectionToken || this.getConnectionTokenFromLocation(); this.logsPath = '/web/logs'; @@ -182,4 +184,21 @@ export class BrowserWorkbenchEnvironmentService implements IEnvironmentService { get webviewCspSource(): string { return this.webviewEndpoint ? this.webviewEndpoint : 'vscode-resource:'; } + + private getConnectionTokenFromLocation(): string | undefined { + // TODO: Check with @alexd where the token will be: search or hash? + let connectionToken: string | undefined = undefined; + if (document.location.search) { + connectionToken = this.getConnectionToken(document.location.search); + } + if (!connectionToken && document.location.hash) { + connectionToken = this.getConnectionToken(document.location.hash); + } + return connectionToken; + } + + private getConnectionToken(str: string): string | undefined { + const m = str.match(/[#&]tkn=([^&]+)/); + return m ? m[1] : undefined; + } } diff --git a/src/vs/workbench/services/extensions/common/abstractExtensionService.ts b/src/vs/workbench/services/extensions/common/abstractExtensionService.ts index 886da1e35d..0e9007755a 100644 --- a/src/vs/workbench/services/extensions/common/abstractExtensionService.ts +++ b/src/vs/workbench/services/extensions/common/abstractExtensionService.ts @@ -263,6 +263,11 @@ export abstract class AbstractExtensionService extends Disposable implements IEx return 0; } + public async setRemoteEnvironment(env: { [key: string]: string | null }): Promise { + await this._extensionHostProcessManagers + .map(manager => manager.setRemoteEnvironment(env)); + } + //#endregion // --- impl diff --git a/src/vs/workbench/services/extensions/common/extensionHostProcessManager.ts b/src/vs/workbench/services/extensions/common/extensionHostProcessManager.ts index 93b1c12748..9f8bda8d3d 100644 --- a/src/vs/workbench/services/extensions/common/extensionHostProcessManager.ts +++ b/src/vs/workbench/services/extensions/common/extensionHostProcessManager.ts @@ -290,6 +290,15 @@ export class ExtensionHostProcessManager extends Disposable { } return proxy.$deltaExtensions(toAdd, toRemove); } + + public async setRemoteEnvironment(env: { [key: string]: string | null }): Promise { + const proxy = await this._getExtensionHostProcessProxy(); + if (!proxy) { + return; + } + + return proxy.$setRemoteEnvironment(env); + } } const colorTables = [ diff --git a/src/vs/workbench/services/extensions/common/extensions.ts b/src/vs/workbench/services/extensions/common/extensions.ts index 3f66df503d..b6af9700c0 100644 --- a/src/vs/workbench/services/extensions/common/extensions.ts +++ b/src/vs/workbench/services/extensions/common/extensions.ts @@ -229,6 +229,12 @@ export interface IExtensionService { */ stopExtensionHost(): void; + /** + * Modify the environment of the remote extension host + * @param env New properties for the remote extension host + */ + setRemoteEnvironment(env: { [key: string]: string | null }): Promise; + _logOrShowMessage(severity: Severity, msg: string): void; _activateById(extensionId: ExtensionIdentifier, activationEvent: string): Promise; _onWillActivateExtension(extensionId: ExtensionIdentifier): void; @@ -278,6 +284,7 @@ export class NullExtensionService implements IExtensionService { restartExtensionHost(): void { } startExtensionHost(): void { } stopExtensionHost(): void { } + async setRemoteEnvironment(_env: { [key: string]: string | null }): Promise { } canAddExtension(): boolean { return false; } canRemoveExtension(): boolean { return false; } _logOrShowMessage(_severity: Severity, _msg: string): void { } diff --git a/src/vs/workbench/services/extensions/common/remoteExtensionHostClient.ts b/src/vs/workbench/services/extensions/common/remoteExtensionHostClient.ts index cfe06f03be..c249bcb8a2 100644 --- a/src/vs/workbench/services/extensions/common/remoteExtensionHostClient.ts +++ b/src/vs/workbench/services/extensions/common/remoteExtensionHostClient.ts @@ -71,7 +71,6 @@ export class RemoteExtensionHostClient extends Disposable implements IExtensionH public start(): Promise { const options: IConnectionOptions = { - isBuilt: this._environmentService.isBuilt, commit: this._productService.commit, socketFactory: this._socketFactory, addressProvider: { diff --git a/src/vs/workbench/services/label/common/labelService.ts b/src/vs/workbench/services/label/common/labelService.ts index 004a93d3ff..db4a000617 100644 --- a/src/vs/workbench/services/label/common/labelService.ts +++ b/src/vs/workbench/services/label/common/labelService.ts @@ -68,7 +68,7 @@ const resourceLabelFormattersExtPoint = ExtensionsRegistry.registerExtensionPoin }); const sepRegexp = /\//g; -const labelMatchingRegexp = /\$\{scheme\}|\$\{authority\}|\$\{path\}/g; +const labelMatchingRegexp = /\$\{(scheme|authority|path|(query)\.(.+?))\}/g; function hasDriveLetter(path: string): boolean { return !!(isWindows && path && path[2] === ':'); @@ -222,12 +222,23 @@ export class LabelService implements ILabelService { } private formatUri(resource: URI, formatting: ResourceLabelFormatting, forceNoTildify?: boolean): string { - let label = formatting.label.replace(labelMatchingRegexp, match => { - switch (match) { - case '${scheme}': return resource.scheme; - case '${authority}': return resource.authority; - case '${path}': return resource.path; - default: return ''; + let label = formatting.label.replace(labelMatchingRegexp, (match, token, qsToken, qsValue) => { + switch (token) { + case 'scheme': return resource.scheme; + case 'authority': return resource.authority; + case 'path': return resource.path; + default: { + if (qsToken === 'query') { + const { query } = resource; + if (query && query[0] === '{' && query[query.length - 1] === '}') { + try { + return JSON.parse(query)[qsValue] || ''; + } + catch { } + } + } + return ''; + } } }); @@ -265,4 +276,4 @@ export class LabelService implements ILabelService { } } -registerSingleton(ILabelService, LabelService, true); \ No newline at end of file +registerSingleton(ILabelService, LabelService, true); diff --git a/src/vs/workbench/services/label/test/label.test.ts b/src/vs/workbench/services/label/test/label.test.ts index 82cc83707a..87cf772299 100644 --- a/src/vs/workbench/services/label/test/label.test.ts +++ b/src/vs/workbench/services/label/test/label.test.ts @@ -97,4 +97,64 @@ suite('URI Label', () => { const uri1 = URI.parse('vscode://microsoft.com/1/2/3/4/5'); assert.equal(labelService.getUriLabel(uri1, { relative: false }), 'second'); }); + + test('custom query', function () { + labelService.registerFormatter({ + scheme: 'vscode', + formatting: { + label: 'LABEL${query.prefix}: ${query.path}/END', + separator: '/', + tildify: true, + normalizeDriveLetter: true + } + }); + + const uri1 = URI.parse(`vscode://microsoft.com/1/2/3/4/5?${encodeURIComponent(JSON.stringify({ prefix: 'prefix', path: 'path' }))}`); + assert.equal(labelService.getUriLabel(uri1, { relative: false }), 'LABELprefix: path/END'); + }); + + test('custom query without value', function () { + labelService.registerFormatter({ + scheme: 'vscode', + formatting: { + label: 'LABEL${query.prefix}: ${query.path}/END', + separator: '/', + tildify: true, + normalizeDriveLetter: true + } + }); + + const uri1 = URI.parse(`vscode://microsoft.com/1/2/3/4/5?${encodeURIComponent(JSON.stringify({ path: 'path' }))}`); + assert.equal(labelService.getUriLabel(uri1, { relative: false }), 'LABEL: path/END'); + }); + + test('custom query without query json', function () { + labelService.registerFormatter({ + scheme: 'vscode', + formatting: { + label: 'LABEL${query.prefix}: ${query.path}/END', + separator: '/', + tildify: true, + normalizeDriveLetter: true + } + }); + + const uri1 = URI.parse('vscode://microsoft.com/1/2/3/4/5?path=foo'); + assert.equal(labelService.getUriLabel(uri1, { relative: false }), 'LABEL: /END'); + }); + + test('custom query without query', function () { + labelService.registerFormatter({ + scheme: 'vscode', + formatting: { + label: 'LABEL${query.prefix}: ${query.path}/END', + separator: '/', + tildify: true, + normalizeDriveLetter: true + } + }); + + const uri1 = URI.parse('vscode://microsoft.com/1/2/3/4/5'); + assert.equal(labelService.getUriLabel(uri1, { relative: false }), 'LABEL: /END'); + }); }); diff --git a/src/vs/workbench/services/remote/browser/remoteAgentServiceImpl.ts b/src/vs/workbench/services/remote/browser/remoteAgentServiceImpl.ts index 1a0724bc96..b5345d054f 100644 --- a/src/vs/workbench/services/remote/browser/remoteAgentServiceImpl.ts +++ b/src/vs/workbench/services/remote/browser/remoteAgentServiceImpl.ts @@ -28,7 +28,7 @@ export class RemoteAgentService extends AbstractRemoteAgentService implements IR super(environmentService); this.socketFactory = new BrowserSocketFactory(webSocketFactory); - this._connection = this._register(new RemoteAgentConnection(environmentService.configuration.remoteAuthority!, productService.commit, this.socketFactory, environmentService, remoteAuthorityResolverService, signService)); + this._connection = this._register(new RemoteAgentConnection(environmentService.configuration.remoteAuthority!, productService.commit, this.socketFactory, remoteAuthorityResolverService, signService)); } getConnection(): IRemoteAgentConnection | null { diff --git a/src/vs/workbench/services/remote/common/abstractRemoteAgentService.ts b/src/vs/workbench/services/remote/common/abstractRemoteAgentService.ts index 33ea5e414f..8cc8f15dbd 100644 --- a/src/vs/workbench/services/remote/common/abstractRemoteAgentService.ts +++ b/src/vs/workbench/services/remote/common/abstractRemoteAgentService.ts @@ -84,7 +84,6 @@ export class RemoteAgentConnection extends Disposable implements IRemoteAgentCon remoteAuthority: string, private readonly _commit: string | undefined, private readonly _socketFactory: ISocketFactory, - private readonly _environmentService: IEnvironmentService, private readonly _remoteAuthorityResolverService: IRemoteAuthorityResolverService, private readonly _signService: ISignService ) { @@ -111,7 +110,6 @@ export class RemoteAgentConnection extends Disposable implements IRemoteAgentCon private async _createConnection(): Promise> { let firstCall = true; const options: IConnectionOptions = { - isBuilt: this._environmentService.isBuilt, commit: this._commit, socketFactory: this._socketFactory, addressProvider: { diff --git a/src/vs/workbench/services/remote/electron-browser/remoteAgentServiceImpl.ts b/src/vs/workbench/services/remote/electron-browser/remoteAgentServiceImpl.ts index 03a94805cc..b72a21d935 100644 --- a/src/vs/workbench/services/remote/electron-browser/remoteAgentServiceImpl.ts +++ b/src/vs/workbench/services/remote/electron-browser/remoteAgentServiceImpl.ts @@ -27,7 +27,7 @@ export class RemoteAgentService extends AbstractRemoteAgentService implements IR super(environmentService); this.socketFactory = nodeSocketFactory; if (remoteAuthority) { - this._connection = this._register(new RemoteAgentConnection(remoteAuthority, product.commit, nodeSocketFactory, environmentService, remoteAuthorityResolverService, signService)); + this._connection = this._register(new RemoteAgentConnection(remoteAuthority, product.commit, nodeSocketFactory, remoteAuthorityResolverService, signService)); } } diff --git a/src/vs/workbench/services/remote/node/tunnelService.ts b/src/vs/workbench/services/remote/node/tunnelService.ts index 9182754c8c..c454cc80cc 100644 --- a/src/vs/workbench/services/remote/node/tunnelService.ts +++ b/src/vs/workbench/services/remote/node/tunnelService.ts @@ -100,7 +100,6 @@ export class TunnelService implements ITunnelService { } const options: IConnectionOptions = { - isBuilt: this.environmentService.isBuilt, commit: product.commit, socketFactory: nodeSocketFactory, addressProvider: { diff --git a/src/vs/workbench/test/electron-browser/api/extHostConfiguration.test.ts b/src/vs/workbench/test/electron-browser/api/extHostConfiguration.test.ts index 1df276538c..389601f20e 100644 --- a/src/vs/workbench/test/electron-browser/api/extHostConfiguration.test.ts +++ b/src/vs/workbench/test/electron-browser/api/extHostConfiguration.test.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import * as assert from 'assert'; -import { URI } from 'vs/base/common/uri'; +import { URI, UriComponents } from 'vs/base/common/uri'; import { ExtHostWorkspace } from 'vs/workbench/api/common/extHostWorkspace'; import { ExtHostConfigProvider } from 'vs/workbench/api/common/extHostConfiguration'; import { MainThreadConfigurationShape, IConfigurationInitData } from 'vs/workbench/api/common/extHost.protocol'; @@ -12,7 +12,7 @@ import { ConfigurationModel } from 'vs/platform/configuration/common/configurati import { TestRPCProtocol } from './testRPCProtocol'; import { mock } from 'vs/workbench/test/electron-browser/api/mock'; import { IWorkspaceFolder, WorkspaceFolder } from 'vs/platform/workspace/common/workspace'; -import { ConfigurationTarget } from 'vs/platform/configuration/common/configuration'; +import { ConfigurationTarget, IConfigurationModel } from 'vs/platform/configuration/common/configuration'; import { NullLogService } from 'vs/platform/log/common/log'; import { assign } from 'vs/base/common/objects'; import { Counter } from 'vs/base/common/numbers'; @@ -39,7 +39,7 @@ suite('ExtHostConfiguration', function () { defaults: new ConfigurationModel(contents), user: new ConfigurationModel(contents), workspace: new ConfigurationModel(), - folders: Object.create(null), + folders: [], configurationScopes: [] }; } @@ -277,7 +277,7 @@ suite('ExtHostConfiguration', function () { } }, ['editor.wordWrap']), workspace: new ConfigurationModel({}, []), - folders: Object.create(null), + folders: [], configurationScopes: [] } ); @@ -297,13 +297,13 @@ suite('ExtHostConfiguration', function () { test('inspect in single root context', function () { const workspaceUri = URI.file('foo'); - const folders = Object.create(null); + const folders: [UriComponents, IConfigurationModel][] = []; const workspace = new ConfigurationModel({ 'editor': { 'wordWrap': 'bounded' } }, ['editor.wordWrap']); - folders[workspaceUri.toString()] = workspace; + folders.push([workspaceUri, workspace]); const extHostWorkspace = new ExtHostWorkspace(new TestRPCProtocol(), new NullLogService(), new Counter()); extHostWorkspace.$initializeWorkspace({ 'id': 'foo', @@ -365,19 +365,19 @@ suite('ExtHostConfiguration', function () { const firstRoot = URI.file('foo1'); const secondRoot = URI.file('foo2'); const thirdRoot = URI.file('foo3'); - const folders = Object.create(null); - folders[firstRoot.toString()] = new ConfigurationModel({ + const folders: [UriComponents, IConfigurationModel][] = []; + folders.push([firstRoot, new ConfigurationModel({ 'editor': { 'wordWrap': 'off', 'lineNumbers': 'relative' } - }, ['editor.wordWrap']); - folders[secondRoot.toString()] = new ConfigurationModel({ + }, ['editor.wordWrap'])]); + folders.push([secondRoot, new ConfigurationModel({ 'editor': { 'wordWrap': 'on' } - }, ['editor.wordWrap']); - folders[thirdRoot.toString()] = new ConfigurationModel({}, []); + }, ['editor.wordWrap'])]); + folders.push([thirdRoot, new ConfigurationModel({}, [])]); const extHostWorkspace = new ExtHostWorkspace(new TestRPCProtocol(), new NullLogService(), new Counter()); extHostWorkspace.$initializeWorkspace({ diff --git a/test/smoke/src/areas/statusbar/statusbar.ts b/test/smoke/src/areas/statusbar/statusbar.ts index 42da9019ac..c477b0a1cb 100644 --- a/test/smoke/src/areas/statusbar/statusbar.ts +++ b/test/smoke/src/areas/statusbar/statusbar.ts @@ -60,9 +60,9 @@ export class StatusBar { case StatusBarElement.LANGUAGE_STATUS: return `${this.mainSelector} ${this.rightSelector}[title="Select Language Mode"]`; case StatusBarElement.FEEDBACK_ICON: - return `${this.mainSelector} ${this.rightSelector} .monaco-dropdown.send-feedback`; + return `${this.mainSelector} .statusbar-item.right[id="status.feedback"]`; default: throw new Error(element); } } -} \ No newline at end of file +} diff --git a/test/smoke/src/areas/workbench/data-loss.test.ts b/test/smoke/src/areas/workbench/data-loss.test.ts index 4372bf410d..bec56cbe51 100644 --- a/test/smoke/src/areas/workbench/data-loss.test.ts +++ b/test/smoke/src/areas/workbench/data-loss.test.ts @@ -12,7 +12,7 @@ export function setup() { await app.workbench.editors.newUntitledFile(); const untitled = 'Untitled-1'; - const textToTypeInUntitled = 'Hello, Unitled Code'; + const textToTypeInUntitled = 'Hello, Untitled Code'; await app.workbench.editor.waitForTypeInEditor(untitled, textToTypeInUntitled); const readmeMd = 'readme.md'; @@ -30,4 +30,4 @@ export function setup() { await app.workbench.editor.waitForEditorContents(untitled, c => c.indexOf(textToTypeInUntitled) > -1); }); }); -} \ No newline at end of file +} diff --git a/test/smoke/src/areas/workbench/localization.test.ts b/test/smoke/src/areas/workbench/localization.test.ts index 3feda99159..07c9b8c237 100644 --- a/test/smoke/src/areas/workbench/localization.test.ts +++ b/test/smoke/src/areas/workbench/localization.test.ts @@ -39,8 +39,8 @@ export function setup() { await app.workbench.debug.openDebugViewlet(); await app.workbench.debug.waitForTitle(title => /debug/i.test(title)); - await app.workbench.extensions.openExtensionsViewlet(); - await app.workbench.extensions.waitForTitle(title => /erweiterungen/i.test(title)); + // await app.workbench.extensions.openExtensionsViewlet(); + // await app.workbench.extensions.waitForTitle(title => /erweiterungen/i.test(title)); }); }); -} \ No newline at end of file +} diff --git a/yarn.lock b/yarn.lock index 2a952624fb..2ff20de298 100644 --- a/yarn.lock +++ b/yarn.lock @@ -10236,10 +10236,10 @@ xterm-addon-web-links@0.1.0-beta10: resolved "https://registry.yarnpkg.com/xterm-addon-web-links/-/xterm-addon-web-links-0.1.0-beta10.tgz#610fa9773a2a5ccd41c1c83ba0e2dd2c9eb66a23" integrity sha512-xfpjy0V6bB4BR44qIgZQPoCMVakxb65gMscPkHpO//QxvUxKzabV3dxOsIbeZRFkUGsWTFlvz2OoaBLoNtv5gg== -xterm@3.15.0-beta89: - version "3.15.0-beta89" - resolved "https://registry.yarnpkg.com/xterm/-/xterm-3.15.0-beta89.tgz#255962e2595deefb42b8c0043001256526163a3f" - integrity sha512-rNaoUamacPRg+ejbKDGRDNqR3SZ3Uf/pUW0mO+FF25/lIgdLq8x7RgZVBgFweCZ/dijPjxoyMcgfNDTH9h8LOg== +xterm@3.15.0-beta90: + version "3.15.0-beta90" + resolved "https://registry.yarnpkg.com/xterm/-/xterm-3.15.0-beta90.tgz#e1732c2914584c86cffa797ba762c482f21ce182" + integrity sha512-eixIA5brfoez+Y8bJPCcIw8Q7LgOvxRX3cPBaGmo7ozUASx9IEGOmvIRQX1ozTUmxEiXPnAxOfl/isQ+yNlaww== y18n@^3.2.1: version "3.2.1"