diff options
author | Miguel Solorio <miguel.solorio@microsoft.com> | 2019-10-14 20:48:09 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-10-14 20:48:09 +0300 |
commit | 12625aaffdff528debdb242fe603a6b3acf2a914 (patch) | |
tree | 49a90d16646fe23e319423003d277d0d0850e766 | |
parent | 85fe047664ea6ac101ea4fc42059a2a52bf89c30 (diff) | |
parent | c534a1cea90293f29edb2995917fe3e267a11716 (diff) |
Merge branch 'master' into misolori/monokai-theme
100 files changed, 1314 insertions, 942 deletions
diff --git a/extensions/markdown-language-features/package.json b/extensions/markdown-language-features/package.json index 482d0e6133d..29cef108b98 100644 --- a/extensions/markdown-language-features/package.json +++ b/extensions/markdown-language-features/package.json @@ -317,8 +317,8 @@ "build-preview": "webpack --mode production" }, "dependencies": { - "highlight.js": "9.15.8", - "markdown-it": "^9.1.0", + "highlight.js": "9.15.10", + "markdown-it": "^10.0.0", "markdown-it-front-matter": "^0.1.2", "vscode-extension-telemetry": "0.1.1", "vscode-nls": "^4.0.0" diff --git a/extensions/markdown-language-features/yarn.lock b/extensions/markdown-language-features/yarn.lock index a45f00885e8..ccaebc2cbe6 100644 --- a/extensions/markdown-language-features/yarn.lock +++ b/extensions/markdown-language-features/yarn.lock @@ -1973,10 +1973,10 @@ enhanced-resolve@^4.0.0: memory-fs "^0.4.0" tapable "^1.0.0" -entities@~1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/entities/-/entities-1.1.1.tgz#6e5c2d0a5621b5dadaecef80b90edfb5cd7772f0" - integrity sha1-blwtClYhtdra7O+AuQ7ftc13cvA= +entities@~2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/entities/-/entities-2.0.0.tgz#68d6084cab1b079767540d80e56a39b423e4abf4" + integrity sha512-D9f7V0JSRwIxlRI2mjMqufDrRDnx8p+eEOz7aUM9SuvF8gsBzra0/6tbjl1m8eQHrZlYj6PxqE00hZ1SAIKPLw== errno@^0.1.3, errno@~0.1.7: version "0.1.7" @@ -2933,10 +2933,10 @@ he@1.1.1: resolved "https://registry.yarnpkg.com/he/-/he-1.1.1.tgz#93410fd21b009735151f8868c2f271f3427e23fd" integrity sha1-k0EP0hsAlzUVH4howvJx80J+I/0= -highlight.js@9.15.8: - version "9.15.8" - resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-9.15.8.tgz#f344fda123f36f1a65490e932cf90569e4999971" - integrity sha512-RrapkKQWwE+wKdF73VsOa2RQdIoO3mxwJ4P8mhbI6KYJUraUHRKM5w5zQQKXNk0xNL4UVRdulV9SBJcmzJNzVA== +highlight.js@9.15.10: + version "9.15.10" + resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-9.15.10.tgz#7b18ed75c90348c045eef9ed08ca1319a2219ad2" + integrity sha512-RoV7OkQm0T3os3Dd2VHLNMoaoDVx77Wygln3n9l5YV172XonWG6rgQD3XnF/BuFFZw9A0TJgmMSO8FEWQgvcXw== hmac-drbg@^1.0.0: version "1.0.1" @@ -3900,13 +3900,13 @@ markdown-it-front-matter@^0.1.2: resolved "https://registry.yarnpkg.com/markdown-it-front-matter/-/markdown-it-front-matter-0.1.2.tgz#e50bf56e77e6a4f5ac4ffa894d4d45ccd9896b20" integrity sha1-5Qv1bnfmpPWsT/qJTU1FzNmJayA= -markdown-it@^9.1.0: - version "9.1.0" - resolved "https://registry.yarnpkg.com/markdown-it/-/markdown-it-9.1.0.tgz#df9601c168568704d554b1fff9af0c5b561168d9" - integrity sha512-xHKG4C8iPriyfu/jc2hsCC045fKrMQ0VexX2F1FGYiRxDxqMB2aAhF8WauJ3fltn2kb90moGBkiiEdooGIg55w== +markdown-it@^10.0.0: + version "10.0.0" + resolved "https://registry.yarnpkg.com/markdown-it/-/markdown-it-10.0.0.tgz#abfc64f141b1722d663402044e43927f1f50a8dc" + integrity sha512-YWOP1j7UbDNz+TumYP1kpwnP0aEa711cJjrAQrzd0UXlbJfc5aAq0F/PZHjiioqDC1NKgvIMX+o+9Bk7yuM2dg== dependencies: argparse "^1.0.7" - entities "~1.1.1" + entities "~2.0.0" linkify-it "^2.0.0" mdurl "^1.0.1" uc.micro "^1.0.5" diff --git a/extensions/npm/README.md b/extensions/npm/README.md index 941da175102..f3707f85d32 100644 --- a/extensions/npm/README.md +++ b/extensions/npm/README.md @@ -22,6 +22,10 @@ The Npm Script Explorer shows the npm scripts found in your workspace. The explo The extension supports to run the selected script as a task when editing the `package.json`file. You can either run a script from the hover shown on a script or using the command `Run Selected Npm Script`. +### Run Scripts from a Folder in the Explorer + +The extension supports running a script as a task from a folder in the Explorer. The command `Run NPM Script in Folder...` shown in the Explorer context menu finds all scripts in `package.json` files that are contained in this folder. You can then select the script to be executed as a task from the resulting list. You enable this support with the `npm.runScriptFromFolder` which is `false` by default. + ### Others The extension fetches data from https://registry.npmjs.org and https://registry.bower.io to provide auto-completion and information on hover features on npm dependencies. @@ -34,5 +38,7 @@ The extension fetches data from https://registry.npmjs.org and https://registry. - `npm.exclude` - Glob patterns for folders that should be excluded from automatic script detection. The pattern is matched against the **absolute path** of the package.json. For example, to exclude all test folders use '**/test/**'. - `npm.enableScriptExplorer` - Enable an explorer view for npm scripts. - `npm.scriptExplorerAction` - The default click action: `open` or `run`, the default is `open`. +- `npm.enableRunFromFolder` - Enable running npm scripts from the context menu of folders in Explorer, the default is `false`. - `npm.scriptCodeLens.enable` - Enable/disable the code lenses to run a script, the default is `false`. + diff --git a/extensions/npm/package.json b/extensions/npm/package.json index a987d6082b4..64782111ec5 100644 --- a/extensions/npm/package.json +++ b/extensions/npm/package.json @@ -88,6 +88,10 @@ { "command": "npm.runSelectedScript", "title": "%command.runSelectedScript%" + }, + { + "command": "npm.runScriptFromFolder", + "title": "%command.runScriptFromFolder%" } ], "menus": { @@ -115,6 +119,10 @@ { "command": "npm.runSelectedScript", "when": "false" + }, + { + "command": "npm.runScriptFromFolder", + "when": "false" } ], "editor/context": [ @@ -172,7 +180,14 @@ "when": "view == npm && viewItem == script", "group": "navigation@3" } - ] + ], + "explorer/context": [ + { + "when": "config.npm.enableRunFromFolder && explorerViewletVisible && explorerResourceIsFolder", + "command": "npm.runScriptFromFolder", + "group": "2_workspace" + } + ] }, "configuration": { "id": "npm", @@ -222,6 +237,12 @@ "scope": "resource", "description": "%config.npm.enableScriptExplorer%" }, + "npm.enableRunFromFolder": { + "type": "boolean", + "default": false, + "scope": "resource", + "description": "%config.npm.enableRunFromFolder%" + }, "npm.scriptExplorerAction": { "type": "string", "enum": [ diff --git a/extensions/npm/package.nls.json b/extensions/npm/package.nls.json index b5e00dd614b..014010a8425 100644 --- a/extensions/npm/package.nls.json +++ b/extensions/npm/package.nls.json @@ -1,21 +1,23 @@ { "description": "Extension to add task support for npm scripts.", - "displayName": "Npm support for VS Code", + "displayName": "NPM support for VS Code", "config.npm.autoDetect": "Controls whether npm scripts should be automatically detected.", "config.npm.runSilent": "Run npm commands with the `--silent` option.", "config.npm.packageManager": "The package manager used to run scripts.", "config.npm.exclude": "Configure glob patterns for folders that should be excluded from automatic script detection.", "config.npm.enableScriptExplorer": "Enable an explorer view for npm scripts when there is no top-level 'package.json' file.", - "config.npm.scriptExplorerAction": "The default click action used in the scripts explorer: `open` or `run`, the default is `open`.", + "config.npm.scriptExplorerAction": "The default click action used in the npm scripts explorer: `open` or `run`, the default is `open`.", + "config.npm.enableRunFromFolder": "Enable running NPM scripts contained in a folder from the Explorer context menu.", "config.npm.fetchOnlinePackageInfo": "Fetch data from https://registry.npmjs.org and https://registry.bower.io to provide auto-completion and information on hover features on npm dependencies.", "npm.parseError": "Npm task detection: failed to parse the file {0}", "taskdef.script": "The npm script to customize.", "taskdef.path": "The path to the folder of the package.json file that provides the script. Can be omitted.", - "view.name": "Npm Scripts", + "view.name": "NPM Scripts", "command.refresh": "Refresh", "command.run": "Run", "command.debug": "Debug", "command.openScript": "Open", "command.runInstall": "Run Install", - "command.runSelectedScript": "Run Script" + "command.runSelectedScript": "Run Script", + "command.runScriptFromFolder": "Run NPM Script in Folder..." } diff --git a/extensions/npm/src/commands.ts b/extensions/npm/src/commands.ts index 08384681708..7ca92879f9b 100644 --- a/extensions/npm/src/commands.ts +++ b/extensions/npm/src/commands.ts @@ -3,11 +3,15 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +import * as nls from 'vscode-nls'; import * as vscode from 'vscode'; + import { - runScript, findScriptAtPosition + detectNpmScriptsForFolder, + findScriptAtPosition, + runScript, + FolderTaskItem } from './tasks'; -import * as nls from 'vscode-nls'; const localize = nls.loadMessageBundle(); @@ -28,4 +32,37 @@ export function runSelectedScript() { let message = localize('noScriptFound', 'Could not find a valid npm script at the selection.'); vscode.window.showErrorMessage(message); } -}
\ No newline at end of file +} + +export async function selectAndRunScriptFromFolder(selectedFolder: vscode.Uri) { + let taskList: FolderTaskItem[] = await detectNpmScriptsForFolder(selectedFolder); + + if (taskList && taskList.length > 0) { + const quickPick = vscode.window.createQuickPick<FolderTaskItem>(); + quickPick.title = 'Run NPM script in Folder'; + quickPick.placeholder = 'Select an npm script'; + quickPick.items = taskList; + + const toDispose: vscode.Disposable[] = []; + + let pickPromise = new Promise<FolderTaskItem | undefined>((c) => { + toDispose.push(quickPick.onDidAccept(() => { + toDispose.forEach(d => d.dispose()); + c(quickPick.selectedItems[0]); + })); + toDispose.push(quickPick.onDidHide(() => { + toDispose.forEach(d => d.dispose()); + c(undefined); + })); + }); + quickPick.show(); + let result = await pickPromise; + quickPick.dispose(); + if (result) { + vscode.tasks.executeTask(result.task); + } + } + else { + vscode.window.showInformationMessage(`No npm scripts found in ${selectedFolder.fsPath}`, { modal: true }); + } +} diff --git a/extensions/npm/src/main.ts b/extensions/npm/src/main.ts index d32d245b0ed..3777f393757 100644 --- a/extensions/npm/src/main.ts +++ b/extensions/npm/src/main.ts @@ -6,10 +6,10 @@ import * as httpRequest from 'request-light'; import * as vscode from 'vscode'; import { addJSONProviders } from './features/jsonContributions'; +import { runSelectedScript, selectAndRunScriptFromFolder } from './commands'; import { NpmScriptsTreeDataProvider } from './npmView'; import { invalidateTasksCache, NpmTaskProvider, hasPackageJson } from './tasks'; import { invalidateHoverScriptsCache, NpmScriptHoverProvider } from './scriptHover'; -import { runSelectedScript } from './commands'; let treeDataProvider: NpmScriptsTreeDataProvider | undefined; @@ -45,6 +45,8 @@ export async function activate(context: vscode.ExtensionContext): Promise<void> if (await hasPackageJson()) { vscode.commands.executeCommand('setContext', 'npm:showScriptExplorer', true); } + + context.subscriptions.push(vscode.commands.registerCommand('npm.runScriptFromFolder', selectAndRunScriptFromFolder)); } function registerTaskProvider(context: vscode.ExtensionContext): vscode.Disposable | undefined { diff --git a/extensions/npm/src/tasks.ts b/extensions/npm/src/tasks.ts index 0e6a28bfc33..cc21ffafc8f 100644 --- a/extensions/npm/src/tasks.ts +++ b/extensions/npm/src/tasks.ts @@ -5,7 +5,7 @@ import { TaskDefinition, Task, TaskGroup, WorkspaceFolder, RelativePattern, ShellExecution, Uri, workspace, - DebugConfiguration, debug, TaskProvider, TextDocument, tasks, TaskScope + DebugConfiguration, debug, TaskProvider, TextDocument, tasks, TaskScope, QuickPickItem } from 'vscode'; import * as path from 'path'; import * as fs from 'fs'; @@ -20,6 +20,11 @@ export interface NpmTaskDefinition extends TaskDefinition { path?: string; } +export interface FolderTaskItem extends QuickPickItem { + label: string; + task: Task; +} + type AutoDetect = 'on' | 'off'; let cachedTasks: Task[] | undefined = undefined; @@ -155,6 +160,29 @@ async function detectNpmScripts(): Promise<Task[]> { } } + +export async function detectNpmScriptsForFolder(folder: Uri): Promise<FolderTaskItem[]> { + + let folderTasks: FolderTaskItem[] = []; + + try { + let relativePattern = new RelativePattern(folder.fsPath, '**/package.json'); + let paths = await workspace.findFiles(relativePattern, '**/node_modules/**'); + + let visitedPackageJsonFiles: Set<string> = new Set(); + for (const path of paths) { + if (!visitedPackageJsonFiles.has(path.fsPath)) { + let tasks = await provideNpmScriptsForFolder(path); + visitedPackageJsonFiles.add(path.fsPath); + folderTasks.push(...tasks.map(t => ({ label: t.name, task: t }))); + } + } + return folderTasks; + } catch (error) { + return Promise.reject(error); + } +} + export async function provideNpmScripts(): Promise<Task[]> { if (!cachedTasks) { cachedTasks = await detectNpmScripts(); diff --git a/extensions/php/language-configuration.json b/extensions/php/language-configuration.json index 9c24c7b724b..b9b67d2be50 100644 --- a/extensions/php/language-configuration.json +++ b/extensions/php/language-configuration.json @@ -26,7 +26,7 @@ ], "indentationRules": { "increaseIndentPattern": "({(?!.*}).*|\\(|\\[|((else(\\s)?)?if|else|for(each)?|while|switch|case).*:)\\s*((/[/*].*|)?$|\\?>)", - "decreaseIndentPattern": "^(.*\\*\\/)?\\s*((\\})|(\\)+[;,])|(\\][;,])|\\b(else:)|\\b((end(if|for(each)?|while|switch));))" + "decreaseIndentPattern": "^(.*\\*\\/)?\\s*((\\})|(\\)+[;,])|(\\][;,])|\\b(else:)|\\b((end(if|for(each)?|while|switch)|break);))" }, "folding": { "markers": { diff --git a/package.json b/package.json index 7f469d57bb0..d3c9b20d2d3 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "code-oss-dev", "version": "1.40.0", - "distro": "9627858bf882fef220a55f51257dca1491763dc1", + "distro": "8f2b29933a026f6754ad5093a7c10c803f0ff30f", "author": { "name": "Microsoft Corporation" }, @@ -30,7 +30,7 @@ "dependencies": { "applicationinsights": "1.0.8", "chokidar": "3.1.0", - "graceful-fs": "4.2.2", + "graceful-fs": "4.1.11", "http-proxy-agent": "^2.1.0", "https-proxy-agent": "^2.2.1", "iconv-lite": "0.5.0", @@ -153,4 +153,4 @@ "windows-mutex": "0.3.0", "windows-process-tree": "0.2.4" } -} +}
\ No newline at end of file diff --git a/remote/package.json b/remote/package.json index 15aaa8f30b1..901f3251c84 100644 --- a/remote/package.json +++ b/remote/package.json @@ -5,7 +5,7 @@ "applicationinsights": "1.0.8", "chokidar": "3.1.0", "cookie": "^0.4.0", - "graceful-fs": "4.2.2", + "graceful-fs": "4.1.11", "http-proxy-agent": "^2.1.0", "https-proxy-agent": "^2.2.1", "iconv-lite": "0.5.0", diff --git a/remote/yarn.lock b/remote/yarn.lock index b018aafbaab..584fd61e387 100644 --- a/remote/yarn.lock +++ b/remote/yarn.lock @@ -148,12 +148,7 @@ glob-parent@^5.0.0: dependencies: is-glob "^4.0.1" -graceful-fs@4.2.2: - version "4.2.2" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.2.tgz#6f0952605d0140c1cfdb138ed005775b92d67b02" - integrity sha512-IItsdsea19BoLC7ELy13q1iJFNmd7ofZH5+X/pJr90/nRoPEX0DJo1dHDbgtYWOhJhcCgMDTOw84RZ72q6lB+Q== - -graceful-fs@^4.1.2: +graceful-fs@4.1.11, graceful-fs@^4.1.2: version "4.1.11" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658" integrity sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg= diff --git a/src/main.js b/src/main.js index afe479d6174..8db96e5272b 100644 --- a/src/main.js +++ b/src/main.js @@ -32,6 +32,14 @@ const args = parseCLIArgs(); const userDataPath = getUserDataPath(args); app.setPath('userData', userDataPath); +// Set logs path before app 'ready' event if running portable +// to ensure that no 'logs' folder is created on disk at a +// location outside of the portable directory +// (https://github.com/microsoft/vscode/issues/56651) +if (portable.isPortable) { + app.setAppLogsPath(path.join(userDataPath, 'logs')); +} + // Update cwd based on environment and platform setCurrentWorkingDirectory(); diff --git a/src/vs/base/browser/ui/codiconLabel/codicon/codicon.css b/src/vs/base/browser/ui/codiconLabel/codicon/codicon.css index 2ef19ad074b..123178e101a 100644 --- a/src/vs/base/browser/ui/codiconLabel/codicon/codicon.css +++ b/src/vs/base/browser/ui/codiconLabel/codicon/codicon.css @@ -5,7 +5,7 @@ @font-face { font-family: "codicon"; - src: url("./codicon.ttf?419224353c2d776235f324ad51a4eac2") format("truetype"); + src: url("./codicon.ttf?ee0abf41d2096e0e868bc4a7fa17f194") format("truetype"); } .codicon[class*='codicon-'] { @@ -54,6 +54,7 @@ .codicon-star:before { content: "\ea6a" } .codicon-star-add:before { content: "\ea6a" } .codicon-star-delete:before { content: "\ea6a" } +.codicon-star-empty:before { content: "\ea6a" } .codicon-comment:before { content: "\ea6b" } .codicon-comment-add:before { content: "\ea6b" } .codicon-alert:before { content: "\ea6c" } @@ -69,7 +70,6 @@ .codicon-eye-watch:before { content: "\ea70" } .codicon-circle-filled:before { content: "\ea71" } .codicon-primitive-dot:before { content: "\ea71" } -.codicon-stop:before { content: "\ea72" } .codicon-primitive-square:before { content: "\ea72" } .codicon-edit:before { content: "\ea73" } .codicon-pencil:before { content: "\ea73" } @@ -103,6 +103,21 @@ .codicon-file-add:before { content: "\ea7f" } .codicon-new-folder:before { content: "\ea80" } .codicon-file-directory-create:before { content: "\ea80" } +.codicon-trash:before { content: "\ea81" } +.codicon-trashcan:before { content: "\ea81" } +.codicon-history:before { content: "\ea82" } +.codicon-clock:before { content: "\ea82" } +.codicon-folder:before { content: "\ea83" } +.codicon-file-directory:before { content: "\ea83" } +.codicon-logo-github:before { content: "\ea84" } +.codicon-mark-github:before { content: "\ea84" } +.codicon-github:before { content: "\ea84" } +.codicon-terminal:before { content: "\ea85" } +.codicon-console:before { content: "\ea85" } +.codicon-zap:before { content: "\ea86" } +.codicon-event:before { content: "\ea86" } +.codicon-error:before { content: "\ea87" } +.codicon-stop:before { content: "\ea87" } .codicon-Vector:before { content: "\f101" } .codicon-activate-breakpoints:before { content: "\f102" } .codicon-archive:before { content: "\f103" } @@ -158,118 +173,118 @@ .codicon-color:before { content: "\f135" } .codicon-comment-discussion:before { content: "\f136" } .codicon-compare-changes:before { content: "\f137" } -.codicon-console:before { content: "\f138" } -.codicon-constant:before { content: "\f139" } -.codicon-continue:before { content: "\f13a" } -.codicon-credit-card:before { content: "\f13b" } -.codicon-current-and-breakpoint:before { content: "\f13c" } -.codicon-current:before { content: "\f13d" } -.codicon-dash:before { content: "\f13e" } -.codicon-dashboard:before { content: "\f13f" } -.codicon-database:before { content: "\f140" } -.codicon-debug:before { content: "\f141" } -.codicon-device-camera-video:before { content: "\f142" } -.codicon-device-camera:before { content: "\f143" } -.codicon-device-mobile:before { content: "\f144" } -.codicon-diff-added:before { content: "\f145" } -.codicon-diff-ignored:before { content: "\f146" } -.codicon-diff-modified:before { content: "\f147" } -.codicon-diff-removed:before { content: "\f148" } -.codicon-diff-renamed:before { content: "\f149" } -.codicon-diff:before { content: "\f14a" } -.codicon-discard:before { content: "\f14b" } -.codicon-disconnect-:before { content: "\f14c" } -.codicon-editor-layout:before { content: "\f14d" } -.codicon-ellipsis:before { content: "\f14e" } -.codicon-empty-window:before { content: "\f14f" } -.codicon-enumerator-member:before { content: "\f150" } -.codicon-enumerator:before { content: "\f151" } -.codicon-error:before { content: "\f152" } -.codicon-event:before { content: "\f153" } -.codicon-exclude:before { content: "\f154" } -.codicon-extensions:before { content: "\f155" } -.codicon-eye-closed:before { content: "\f156" } -.codicon-field:before { content: "\f157" } -.codicon-file-binary:before { content: "\f158" } -.codicon-file-code:before { content: "\f159" } -.codicon-file-media:before { content: "\f15a" } -.codicon-file-pdf:before { content: "\f15b" } -.codicon-file-submodule:before { content: "\f15c" } -.codicon-file-symlink-directory:before { content: "\f15d" } -.codicon-file-symlink-file:before { content: "\f15e" } -.codicon-file-zip:before { content: "\f15f" } -.codicon-files:before { content: "\f160" } -.codicon-filter:before { content: "\f161" } -.codicon-flame:before { content: "\f162" } -.codicon-fold-down:before { content: "\f163" } -.codicon-fold-up:before { content: "\f164" } -.codicon-fold:before { content: "\f165" } -.codicon-folder-active:before { content: "\f166" } -.codicon-folder-opened:before { content: "\f167" } -.codicon-folder:before { content: "\f168" } -.codicon-gear:before { content: "\f169" } -.codicon-gift:before { content: "\f16a" } -.codicon-gist-secret:before { content: "\f16b" } -.codicon-gist:before { content: "\f16c" } -.codicon-git-commit:before { content: "\f16d" } -.codicon-git-compare:before { content: "\f16e" } -.codicon-git-merge:before { content: "\f16f" } -.codicon-github-action:before { content: "\f170" } -.codicon-github-alt:before { content: "\f171" } -.codicon-github:before { content: "\f172" } -.codicon-globe:before { content: "\f173" } -.codicon-go-to-file:before { content: "\f174" } -.codicon-grabber:before { content: "\f175" } -.codicon-graph:before { content: "\f176" } -.codicon-gripper:before { content: "\f177" } -.codicon-heart:before { content: "\f178" } -.codicon-history:before { content: "\f179" } -.codicon-home:before { content: "\f17a" } -.codicon-horizontal-rule:before { content: "\f17b" } -.codicon-hubot:before { content: "\f17c" } -.codicon-inbox:before { content: "\f17d" } -.codicon-interface:before { content: "\f17e" } -.codicon-issue-closed:before { content: "\f17f" } -.codicon-issue-reopened:before { content: "\f180" } -.codicon-issues:before { content: "\f181" } -.codicon-italic:before { content: "\f182" } -.codicon-jersey:before { content: "\f183" } -.codicon-json:before { content: "\f184" } -.codicon-kebab-vertical:before { content: "\f185" } -.codicon-key:before { content: "\f186" } -.codicon-keyword:before { content: "\f187" } -.codicon-law:before { content: "\f188" } -.codicon-lightbulb-autofix:before { content: "\f189" } -.codicon-link-external:before { content: "\f18a" } -.codicon-link:before { content: "\f18b" } -.codicon-list-ordered:before { content: "\f18c" } -.codicon-list-unordered:before { content: "\f18d" } -.codicon-live-share:before { content: "\f18e" } -.codicon-loading:before { content: "\f18f" } -.codicon-location:before { content: "\f190" } -.codicon-mail-read:before { content: "\f191" } -.codicon-mail:before { content: "\f192" } -.codicon-markdown:before { content: "\f193" } -.codicon-megaphone:before { content: "\f194" } -.codicon-mention:before { content: "\f195" } -.codicon-method:before { content: "\f196" } -.codicon-milestone:before { content: "\f197" } -.codicon-misc:before { content: "\f198" } -.codicon-mortar-board:before { content: "\f199" } -.codicon-move:before { content: "\f19a" } -.codicon-multiple-windows:before { content: "\f19b" } -.codicon-mute:before { content: "\f19c" } -.codicon-namespace:before { content: "\f19d" } -.codicon-no-newline:before { content: "\f19e" } -.codicon-note:before { content: "\f19f" } -.codicon-numeric:before { content: "\f1a0" } -.codicon-octoface:before { content: "\f1a1" } -.codicon-open-preview:before { content: "\f1a2" } -.codicon-operator:before { content: "\f1a3" } -.codicon-package:before { content: "\f1a4" } -.codicon-paintcan:before { content: "\f1a5" } -.codicon-parameter:before { content: "\f1a6" } -.codicon-pause:before { content: "\f1a7" } +.codicon-constant:before { content: "\f138" } +.codicon-continue:before { content: "\f139" } +.codicon-credit-card:before { content: "\f13a" } +.codicon-current-and-breakpoint:before { content: "\f13b" } +.codicon-current:before { content: "\f13c" } +.codicon-dash:before { content: "\f13d" } +.codicon-dashboard:before { content: "\f13e" } +.codicon-database:before { content: "\f13f" } +.codicon-debug-disconnect:before { content: "\f140" } +.codicon-debug-pause:before { content: "\f141" } +.codicon-debug-restart:before { content: "\f142" } +.codicon-debug-start:before { content: "\f143" } +.codicon-debug-step-into:before { content: "\f144" } +.codicon-debug-step-out:before { content: "\f145" } +.codicon-debug-step-over:before { content: "\f146" } +.codicon-debug-stop:before { content: "\f147" } +.codicon-debug:before { content: "\f148" } +.codicon-device-camera-video:before { content: "\f149" } +.codicon-device-camera:before { content: "\f14a" } +.codicon-device-mobile:before { content: "\f14b" } +.codicon-diff-added:before { content: "\f14c" } +.codicon-diff-ignored:before { content: "\f14d" } +.codicon-diff-modified:before { content: "\f14e" } +.codicon-diff-removed:before { content: "\f14f" } +.codicon-diff-renamed:before { content: "\f150" } +.codicon-diff:before { content: "\f151" } +.codicon-discard:before { content: "\f152" } +.codicon-editor-layout:before { content: "\f153" } +.codicon-ellipsis:before { content: "\f154" } +.codicon-empty-window:before { content: "\f155" } +.codicon-enumerator-member:before { content: "\f156" } +.codicon-enumerator:before { content: "\f157" } +.codicon-exclude:before { content: "\f158" } +.codicon-extensions:before { content: "\f159" } +.codicon-eye-closed:before { content: "\f15a" } +.codicon-field:before { content: "\f15b" } +.codicon-file-binary:before { content: "\f15c" } +.codicon-file-code:before { content: "\f15d" } +.codicon-file-media:before { content: "\f15e" } +.codicon-file-pdf:before { content: "\f15f" } +.codicon-file-submodule:before { content: "\f160" } +.codicon-file-symlink-directory:before { content: "\f161" } +.codicon-file-symlink-file:before { content: "\f162" } +.codicon-file-zip:before { content: "\f163" } +.codicon-files:before { content: "\f164" } +.codicon-filter:before { content: "\f165" } +.codicon-flame:before { content: "\f166" } +.codicon-fold-down:before { content: "\f167" } +.codicon-fold-up:before { content: "\f168" } +.codicon-fold:before { content: "\f169" } +.codicon-folder-active:before { content: "\f16a" } +.codicon-folder-opened:before { content: "\f16b" } +.codicon-gear:before { content: "\f16c" } +.codicon-gift:before { content: "\f16d" } +.codicon-gist-secret:before { content: "\f16e" } +.codicon-gist:before { content: "\f16f" } +.codicon-git-commit:before { content: "\f170" } +.codicon-git-compare:before { content: "\f171" } +.codicon-git-merge:before { content: "\f172" } +.codicon-github-action:before { content: "\f173" } +.codicon-github-alt:before { content: "\f174" } +.codicon-globe:before { content: "\f175" } +.codicon-go-to-file:before { content: "\f176" } +.codicon-grabber:before { content: "\f177" } +.codicon-graph:before { content: "\f178" } +.codicon-gripper:before { content: "\f179" } +.codicon-heart:before { content: "\f17a" } +.codicon-home:before { content: "\f17b" } +.codicon-horizontal-rule:before { content: "\f17c" } +.codicon-hubot:before { content: "\f17d" } +.codicon-inbox:before { content: "\f17e" } +.codicon-interface:before { content: "\f17f" } +.codicon-issue-closed:before { content: "\f180" } +.codicon-issue-reopened:before { content: "\f181" } +.codicon-issues:before { content: "\f182" } +.codicon-italic:before { content: "\f183" } +.codicon-jersey:before { content: "\f184" } +.codicon-json:before { content: "\f185" } +.codicon-kebab-vertical:before { content: "\f186" } +.codicon-key:before { content: "\f187" } +.codicon-keyword:before { content: "\f188" } +.codicon-law:before { content: "\f189" } +.codicon-lightbulb-autofix:before { content: "\f18a" } +.codicon-link-external:before { content: "\f18b" } +.codicon-link:before { content: "\f18c" } +.codicon-list-ordered:before { content: "\f18d" } +.codicon-list-unordered:before { content: "\f18e" } +.codicon-live-share:before { content: "\f18f" } +.codicon-loading:before { content: "\f190" } +.codicon-location:before { content: "\f191" } +.codicon-mail-read:before { content: "\f192" } +.codicon-mail:before { content: "\f193" } +.codicon-markdown:before { content: "\f194" } +.codicon-megaphone:before { content: "\f195" } +.codicon-mention:before { content: "\f196" } +.codicon-method:before { content: "\f197" } +.codicon-milestone:before { content: "\f198" } +.codicon-misc:before { content: "\f199" } +.codicon-mortar-board:before { content: "\f19a" } +.codicon-move:before { content: "\f19b" } +.codicon-multiple-windows:before { content: "\f19c" } +.codicon-mute:before { content: "\f19d" } +.codicon-namespace:before { content: "\f19e" } +.codicon-no-newline:before { content: "\f19f" } +.codicon-note:before { content: "\f1a0" } +.codicon-numeric:before { content: "\f1a1" } +.codicon-octoface:before { content: "\f1a2" } +.codicon-open-preview:before { content: "\f1a3" } +.codicon-operator:before { content: "\f1a4" } +.codicon-package:before { content: "\f1a5" } +.codicon-paintcan:before { content: "\f1a6" } +.codicon-parameter:before { content: "\f1a7" } .codicon-pin:before { content: "\f1a8" } .codicon-play:before { content: "\f1a9" } .codicon-plug:before { content: "\f1aa" } @@ -295,65 +310,58 @@ .codicon-repo-push:before { content: "\f1be" } .codicon-report:before { content: "\f1bf" } .codicon-request-changes:before { content: "\f1c0" } -.codicon-restart:before { content: "\f1c1" } -.codicon-rocket:before { content: "\f1c2" } -.codicon-root-folder-opened:before { content: "\f1c3" } -.codicon-root-folder:before { content: "\f1c4" } -.codicon-rss:before { content: "\f1c5" } -.codicon-ruby:before { content: "\f1c6" } -.codicon-ruler:before { content: "\f1c7" } -.codicon-save-all:before { content: "\f1c8" } -.codicon-save-as:before { content: "\f1c9" } -.codicon-save:before { content: "\f1ca" } -.codicon-screen-full:before { content: "\f1cb" } -.codicon-screen-normal:before { content: "\f1cc" } -.codicon-search-stop:before { content: "\f1cd" } -.codicon-selection:before { content: "\f1ce" } -.codicon-server:before { content: "\f1cf" } -.codicon-settings:before { content: "\f1d0" } -.codicon-shield:before { content: "\f1d1" } -.codicon-smiley:before { content: "\f1d2" } -.codicon-snippet:before { content: "\f1d3" } -.codicon-sort-precedence:before { content: "\f1d4" } -.codicon-split-horizontal:before { content: "\f1d5" } -.codicon-split-vertical:before { content: "\f1d6" } -.codicon-squirrel:before { content: "\f1d7" } -.codicon-star-empty:before { content: "\f1d8" } -.codicon-star-full:before { content: "\f1d9" } -.codicon-star-half:before { content: "\f1da" } -.codicon-start:before { content: "\f1db" } -.codicon-step-into:before { content: "\f1dc" } -.codicon-step-out:before { content: "\f1dd" } -.codicon-step-over:before { content: "\f1de" } -.codicon-string:before { content: "\f1df" } -.codicon-structure:before { content: "\f1e0" } -.codicon-tasklist:before { content: "\f1e1" } -.codicon-telescope:before { content: "\f1e2" } -.codicon-text-size:before { content: "\f1e3" } -.codicon-three-bars:before { content: "\f1e4" } -.codicon-thumbsdown:before { content: "\f1e5" } -.codicon-thumbsup:before { content: "\f1e6" } -.codicon-tools:before { content: "\f1e7" } -.codicon-trash:before { content: "\f1e8" } -.codicon-triangle-down:before { content: "\f1e9" } -.codicon-triangle-left:before { content: "\f1ea" } -.codicon-triangle-right:before { content: "\f1eb" } -.codicon-triangle-up:before { content: "\f1ec" } -.codicon-twitter:before { content: "\f1ed" } -.codicon-unfold:before { content: "\f1ee" } -.codicon-unlock:before { content: "\f1ef" } -.codicon-unmute:before { content: "\f1f0" } -.codicon-unverified:before { content: "\f1f1" } -.codicon-variable:before { content: "\f1f2" } -.codicon-verified:before { content: "\f1f3" } -.codicon-versions:before { content: "\f1f4" } -.codicon-vm-active:before { content: "\f1f5" } -.codicon-vm-outline:before { content: "\f1f6" } -.codicon-vm-running:before { content: "\f1f7" } -.codicon-watch:before { content: "\f1f8" } -.codicon-whitespace:before { content: "\f1f9" } -.codicon-whole-word:before { content: "\f1fa" } -.codicon-window:before { content: "\f1fb" } -.codicon-word-wrap:before { content: "\f1fc" } -.codicon-zoom-in:before { content: "\f1fd" } -.codicon-zoom-out:before { content: "\f1fe" } +.codicon-rocket:before { content: "\f1c1" } +.codicon-root-folder-opened:before { content: "\f1c2" } +.codicon-root-folder:before { content: "\f1c3" } +.codicon-rss:before { content: "\f1c4" } +.codicon-ruby:before { content: "\f1c5" } +.codicon-ruler:before { content: "\f1c6" } +.codicon-save-all:before { content: "\f1c7" } +.codicon-save-as:before { content: "\f1c8" } +.codicon-save:before { content: "\f1c9" } +.codicon-screen-full:before { content: "\f1ca" } +.codicon-screen-normal:before { content: "\f1cb" } +.codicon-search-stop:before { content: "\f1cc" } +.codicon-selection:before { content: "\f1cd" } +.codicon-server:before { content: "\f1ce" } +.codicon-settings:before { content: "\f1cf" } +.codicon-shield:before { content: "\f1d0" } +.codicon-smiley:before { content: "\f1d1" } +.codicon-snippet:before { content: "\f1d2" } +.codicon-sort-precedence:before { content: "\f1d3" } +.codicon-split-horizontal:before { content: "\f1d4" } +.codicon-split-vertical:before { content: "\f1d5" } +.codicon-squirrel:before { content: "\f1d6" } +.codicon-star-full:before { content: "\f1d7" } +.codicon-star-half:before { content: "\f1d8" } +.codicon-string:before { content: "\f1d9" } +.codicon-structure:before { content: "\f1da" } +.codicon-tasklist:before { content: "\f1db" } +.codicon-telescope:before { content: "\f1dc" } +.codicon-text-size:before { content: "\f1dd" } +.codicon-three-bars:before { content: "\f1de" } +.codicon-thumbsdown:before { content: "\f1df" } +.codicon-thumbsup:before { content: "\f1e0" } +.codicon-tools:before { content: "\f1e1" } +.codicon-triangle-down:before { content: "\f1e2" } +.codicon-triangle-left:before { content: "\f1e3" } +.codicon-triangle-right:before { content: "\f1e4" } +.codicon-triangle-up:before { content: "\f1e5" } +.codicon-twitter:before { content: "\f1e6" } +.codicon-unfold:before { content: "\f1e7" } +.codicon-unlock:before { content: "\f1e8" } +.codicon-unmute:before { content: "\f1e9" } +.codicon-unverified:before { content: "\f1ea" } +.codicon-variable:before { content: "\f1eb" } +.codicon-verified:before { content: "\f1ec" } +.codicon-versions:before { content: "\f1ed" } +.codicon-vm-active:before { content: "\f1ee" } +.codicon-vm-outline:before { content: "\f1ef" } +.codicon-vm-running:before { content: "\f1f0" } +.codicon-watch:before { content: "\f1f1" } +.codicon-whitespace:before { content: "\f1f2" } +.codicon-whole-word:before { content: "\f1f3" } +.codicon-window:before { content: "\f1f4" } +.codicon-word-wrap:before { content: "\f1f5" } +.codicon-zoom-in:before { content: "\f1f6" } +.codicon-zoom-out:before { content: "\f1f7" } diff --git a/src/vs/base/browser/ui/codiconLabel/codicon/codicon.ttf b/src/vs/base/browser/ui/codiconLabel/codicon/codicon.ttf Binary files differindex 3424ea95314..5dfe9ce0a86 100644 --- a/src/vs/base/browser/ui/codiconLabel/codicon/codicon.ttf +++ b/src/vs/base/browser/ui/codiconLabel/codicon/codicon.ttf diff --git a/src/vs/base/common/diff/diff.ts b/src/vs/base/common/diff/diff.ts index 0183b199249..abe78fbd8be 100644 --- a/src/vs/base/common/diff/diff.ts +++ b/src/vs/base/common/diff/diff.ts @@ -5,6 +5,7 @@ import { DiffChange } from 'vs/base/common/diff/diffChange'; import { stringHash } from 'vs/base/common/hash'; +import { Constants } from 'vs/base/common/uint'; export class StringDiffSequence implements ISequence { @@ -138,8 +139,8 @@ class DiffChangeHelper { */ constructor() { this.m_changes = []; - this.m_originalStart = Number.MAX_VALUE; - this.m_modifiedStart = Number.MAX_VALUE; + this.m_originalStart = Constants.MAX_SAFE_SMALL_INTEGER; + this.m_modifiedStart = Constants.MAX_SAFE_SMALL_INTEGER; this.m_originalCount = 0; this.m_modifiedCount = 0; } @@ -158,8 +159,8 @@ class DiffChangeHelper { // Reset for the next change this.m_originalCount = 0; this.m_modifiedCount = 0; - this.m_originalStart = Number.MAX_VALUE; - this.m_modifiedStart = Number.MAX_VALUE; + this.m_originalStart = Constants.MAX_SAFE_SMALL_INTEGER; + this.m_modifiedStart = Constants.MAX_SAFE_SMALL_INTEGER; } /** @@ -422,7 +423,7 @@ export class LcsDiff { let diagonalMin = diagonalForwardStart; let diagonalMax = diagonalForwardEnd; let diagonalRelative = (midOriginalArr[0] - midModifiedArr[0]) - diagonalForwardOffset; - let lastOriginalIndex = Number.MIN_VALUE; + let lastOriginalIndex = Constants.MIN_SAFE_SMALL_INTEGER; let historyIndex = this.m_forwardHistory.length - 1; let diagonal: number; @@ -488,7 +489,7 @@ export class LcsDiff { diagonalMin = diagonalReverseStart; diagonalMax = diagonalReverseEnd; diagonalRelative = (midOriginalArr[0] - midModifiedArr[0]) - diagonalReverseOffset; - lastOriginalIndex = Number.MAX_VALUE; + lastOriginalIndex = Constants.MAX_SAFE_SMALL_INTEGER; historyIndex = (deltaIsEven) ? this.m_reverseHistory.length - 1 : this.m_reverseHistory.length - 2; do { diff --git a/src/vs/base/common/labels.ts b/src/vs/base/common/labels.ts index e866c720bc1..a13138fc35e 100644 --- a/src/vs/base/common/labels.ts +++ b/src/vs/base/common/labels.ts @@ -4,12 +4,11 @@ *--------------------------------------------------------------------------------------------*/ import { URI } from 'vs/base/common/uri'; -import { sep, posix, normalize } from 'vs/base/common/path'; +import { sep, posix, normalize, basename as path_basename, dirname as path_dirname } from 'vs/base/common/path'; import { endsWith, startsWithIgnoreCase, rtrim, startsWith } from 'vs/base/common/strings'; import { Schemas } from 'vs/base/common/network'; import { isLinux, isWindows, isMacintosh } from 'vs/base/common/platform'; import { isEqual, basename, relativePath } from 'vs/base/common/resources'; -import { CharCode } from 'vs/base/common/charCode'; export interface IWorkspaceFolderProvider { getWorkspaceFolder(resource: URI): { uri: URI, name?: string } | null; @@ -388,11 +387,8 @@ export function unmnemonicLabel(label: string): string { * Splits a path in name and parent path, supporting both '/' and '\' */ export function splitName(fullPath: string): { name: string, parentPath: string } { - for (let i = fullPath.length - 1; i >= 1; i--) { - const code = fullPath.charCodeAt(i); - if (code === CharCode.Slash || code === CharCode.Backslash) { - return { parentPath: fullPath.substr(0, i), name: fullPath.substr(i + 1) }; - } + if (fullPath.indexOf('/') !== -1) { + return { name: posix.basename(fullPath), parentPath: posix.dirname(fullPath) }; } - return { parentPath: '', name: fullPath }; + return { name: path_basename(fullPath), parentPath: path_dirname(fullPath) }; } diff --git a/src/vs/editor/common/core/uint.ts b/src/vs/base/common/uint.ts index 00e3b872903..0f5a4f8930a 100644 --- a/src/vs/editor/common/core/uint.ts +++ b/src/vs/base/common/uint.ts @@ -3,32 +3,6 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -export class Uint8Matrix { - - private readonly _data: Uint8Array; - public readonly rows: number; - public readonly cols: number; - - constructor(rows: number, cols: number, defaultValue: number) { - const data = new Uint8Array(rows * cols); - for (let i = 0, len = rows * cols; i < len; i++) { - data[i] = defaultValue; - } - - this._data = data; - this.rows = rows; - this.cols = cols; - } - - public get(row: number, col: number): number { - return this._data[row * this.cols + col]; - } - - public set(row: number, col: number, value: number): void { - this._data[row * this.cols + col] = value; - } -} - export const enum Constants { /** * MAX SMI (SMall Integer) as defined in v8. diff --git a/src/vs/base/node/pfs.ts b/src/vs/base/node/pfs.ts index e08289bdce4..980f425f52e 100644 --- a/src/vs/base/node/pfs.ts +++ b/src/vs/base/node/pfs.ts @@ -138,6 +138,20 @@ export async function readdir(path: string): Promise<string[]> { return handleDirectoryChildren(await promisify(fs.readdir)(path)); } +export async function readdirWithFileTypes(path: string): Promise<fs.Dirent[]> { + const children = await promisify(fs.readdir)(path, { withFileTypes: true }); + + // Mac: uses NFD unicode form on disk, but we want NFC + // See also https://github.com/nodejs/node/issues/2165 + if (platform.isMacintosh) { + for (const child of children) { + child.name = normalizeNFC(child.name); + } + } + + return children; +} + export function readdirSync(path: string): string[] { return handleDirectoryChildren(fs.readdirSync(path)); } diff --git a/src/vs/base/node/processes.ts b/src/vs/base/node/processes.ts index 6b3376ec4f1..64e2625d2a5 100644 --- a/src/vs/base/node/processes.ts +++ b/src/vs/base/node/processes.ts @@ -317,13 +317,16 @@ export abstract class AbstractProcess<TProgressData> { export class LineProcess extends AbstractProcess<LineData> { - private stdoutLineDecoder: LineDecoder; - private stderrLineDecoder: LineDecoder; + private stdoutLineDecoder: LineDecoder | null; + private stderrLineDecoder: LineDecoder | null; public constructor(executable: Executable); public constructor(cmd: string, args: string[], shell: boolean, options: CommandOptions); public constructor(arg1: string | Executable, arg2?: string[], arg3?: boolean | ForkOptions, arg4?: CommandOptions) { super(<any>arg1, arg2, <any>arg3, arg4); + + this.stdoutLineDecoder = null; + this.stderrLineDecoder = null; } protected handleExec(cc: ValueCallback<SuccessData>, pp: ProgressCallback<LineData>, error: Error, stdout: Buffer, stderr: Buffer) { @@ -342,24 +345,30 @@ export class LineProcess extends AbstractProcess<LineData> { } protected handleSpawn(childProcess: cp.ChildProcess, cc: ValueCallback<SuccessData>, pp: ProgressCallback<LineData>, ee: ErrorCallback, sync: boolean): void { - this.stdoutLineDecoder = new LineDecoder(); - this.stderrLineDecoder = new LineDecoder(); + const stdoutLineDecoder = new LineDecoder(); + const stderrLineDecoder = new LineDecoder(); childProcess.stdout.on('data', (data: Buffer) => { - const lines = this.stdoutLineDecoder.write(data); + const lines = stdoutLineDecoder.write(data); lines.forEach(line => pp({ line: line, source: Source.stdout })); }); childProcess.stderr.on('data', (data: Buffer) => { - const lines = this.stderrLineDecoder.write(data); + const lines = stderrLineDecoder.write(data); lines.forEach(line => pp({ line: line, source: Source.stderr })); }); + + this.stdoutLineDecoder = stdoutLineDecoder; + this.stderrLineDecoder = stderrLineDecoder; } protected handleClose(data: any, cc: ValueCallback<SuccessData>, pp: ProgressCallback<LineData>, ee: ErrorCallback): void { - [this.stdoutLineDecoder.end(), this.stderrLineDecoder.end()].forEach((line, index) => { - if (line) { - pp({ line: line, source: index === 0 ? Source.stdout : Source.stderr }); - } - }); + const stdoutLine = this.stdoutLineDecoder ? this.stdoutLineDecoder.end() : null; + if (stdoutLine) { + pp({ line: stdoutLine, source: Source.stdout }); + } + const stderrLine = this.stderrLineDecoder ? this.stderrLineDecoder.end() : null; + if (stderrLine) { + pp({ line: stderrLine, source: Source.stderr }); + } } } diff --git a/src/vs/base/test/node/pfs/pfs.test.ts b/src/vs/base/test/node/pfs/pfs.test.ts index 4f09ad2b56d..060913bbe72 100644 --- a/src/vs/base/test/node/pfs/pfs.test.ts +++ b/src/vs/base/test/node/pfs/pfs.test.ts @@ -16,6 +16,7 @@ import { CancellationTokenSource } from 'vs/base/common/cancellation'; import { isWindows, isLinux } from 'vs/base/common/platform'; import { canNormalize } from 'vs/base/common/normalization'; import { VSBuffer } from 'vs/base/common/buffer'; +import { join } from 'path'; const chunkSize = 64 * 1024; const readError = 'Error while reading'; @@ -386,6 +387,31 @@ suite('PFS', () => { } }); + test('readdirWithFileTypes', async () => { + if (canNormalize && typeof process.versions['electron'] !== 'undefined' /* needs electron */) { + const id = uuid.generateUuid(); + const parentDir = path.join(os.tmpdir(), 'vsctests', id); + const testDir = join(parentDir, 'pfs', id); + + const newDir = path.join(testDir, 'öäü'); + await pfs.mkdirp(newDir, 493); + + await pfs.writeFile(join(testDir, 'somefile.txt'), 'contents'); + + assert.ok(fs.existsSync(newDir)); + + const children = await pfs.readdirWithFileTypes(testDir); + + assert.equal(children.some(n => n.name === 'öäü'), true); // Mac always converts to NFD, so + assert.equal(children.some(n => n.isDirectory()), true); + + assert.equal(children.some(n => n.name === 'somefile.txt'), true); + assert.equal(children.some(n => n.isFile()), true); + + await pfs.rimraf(parentDir); + } + }); + test('writeFile (string)', async () => { const smallData = 'Hello World'; const bigData = (new Array(100 * 1024)).join('Large String\n'); diff --git a/src/vs/code/browser/workbench/workbench-dev.html b/src/vs/code/browser/workbench/workbench-dev.html index b59b7a2b49b..9da104d797f 100644 --- a/src/vs/code/browser/workbench/workbench-dev.html +++ b/src/vs/code/browser/workbench/workbench-dev.html @@ -25,7 +25,7 @@ "> <!-- Workbench Configuration --> - <meta id="vscode-workbench-web-configuration" data-settings="{{WORKBENCH_WEB_CONGIGURATION}}"> + <meta id="vscode-workbench-web-configuration" data-settings="{{WORKBENCH_WEB_CONFIGURATION}}"> <!-- Workarounds/Hacks (remote user data uri) --> <meta id="vscode-remote-user-data-uri" data-settings="{{REMOTE_USER_DATA_URI}}"> diff --git a/src/vs/code/browser/workbench/workbench.html b/src/vs/code/browser/workbench/workbench.html index f3caa5350bf..01e0e6c909f 100644 --- a/src/vs/code/browser/workbench/workbench.html +++ b/src/vs/code/browser/workbench/workbench.html @@ -25,7 +25,7 @@ "> <!-- Workbench Configuration --> - <meta id="vscode-workbench-web-configuration" data-settings="{{WORKBENCH_WEB_CONGIGURATION}}"> + <meta id="vscode-workbench-web-configuration" data-settings="{{WORKBENCH_WEB_CONFIGURATION}}"> <!-- Workarounds/Hacks (remote user data uri) --> <meta id="vscode-remote-user-data-uri" data-settings="{{REMOTE_USER_DATA_URI}}"> diff --git a/src/vs/editor/browser/editorBrowser.ts b/src/vs/editor/browser/editorBrowser.ts index 3a05cd5c8f4..0253876b502 100644 --- a/src/vs/editor/browser/editorBrowser.ts +++ b/src/vs/editor/browser/editorBrowser.ts @@ -18,6 +18,7 @@ import { IModelContentChangedEvent, IModelDecorationsChangedEvent, IModelLanguag import { OverviewRulerZone } from 'vs/editor/common/view/overviewZoneManager'; import { IEditorWhitespace } from 'vs/editor/common/viewLayout/whitespaceComputer'; import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; +import { IDiffComputationResult } from 'vs/editor/common/services/editorWorkerService'; /** * A view zone is a full horizontal rectangle that 'pushes' text down. @@ -907,6 +908,12 @@ export interface IDiffEditor extends editorCommon.IEditor { getLineChanges(): editorCommon.ILineChange[] | null; /** + * Get the computed diff information. + * @internal + */ + getDiffComputationResult(): IDiffComputationResult | null; + + /** * Get information based on computed diff about a line number from the original model. * If the diff computation is not finished or the model is missing, will return null. */ diff --git a/src/vs/editor/browser/editorExtensions.ts b/src/vs/editor/browser/editorExtensions.ts index ffccc8832bd..d5b881b3af0 100644 --- a/src/vs/editor/browser/editorExtensions.ts +++ b/src/vs/editor/browser/editorExtensions.ts @@ -6,10 +6,10 @@ import { IPosition } from 'vs/base/browser/ui/contextview/contextview'; import { illegalArgument } from 'vs/base/common/errors'; import { URI } from 'vs/base/common/uri'; -import { ICodeEditor } from 'vs/editor/browser/editorBrowser'; +import { ICodeEditor, IDiffEditor } from 'vs/editor/browser/editorBrowser'; import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService'; import { Position } from 'vs/editor/common/core/position'; -import { IEditorContribution } from 'vs/editor/common/editorCommon'; +import { IEditorContribution, IDiffEditorContribution } from 'vs/editor/common/editorCommon'; import { ITextModel } from 'vs/editor/common/model'; import { IModelService } from 'vs/editor/common/services/modelService'; import { ITextModelService } from 'vs/editor/common/services/resolverService'; @@ -24,6 +24,7 @@ import { withNullAsUndefined } from 'vs/base/common/types'; export type ServicesAccessor = InstantiationServicesAccessor; export type IEditorContributionCtor = IConstructorSignature1<ICodeEditor, IEditorContribution>; +export type IDiffEditorContributionCtor = IConstructorSignature1<IDiffEditor, IDiffEditorContribution>; export type EditorTelemetryDataFragment = { target: { classification: 'SystemMetaData', purpose: 'FeatureInsight', }; snippet: { classification: 'SystemMetaData', purpose: 'FeatureInsight', isMeasurement: true, }; @@ -300,6 +301,10 @@ export function registerEditorContribution(ctor: IEditorContributionCtor): void EditorContributionRegistry.INSTANCE.registerEditorContribution(ctor); } +export function registerDiffEditorContribution(ctor: IDiffEditorContributionCtor): void { + EditorContributionRegistry.INSTANCE.registerDiffEditorContribution(ctor); +} + export namespace EditorExtensionsRegistry { export function getEditorCommand(commandId: string): EditorCommand { @@ -313,6 +318,10 @@ export namespace EditorExtensionsRegistry { export function getEditorContributions(): IEditorContributionCtor[] { return EditorContributionRegistry.INSTANCE.getEditorContributions(); } + + export function getDiffEditorContributions(): IDiffEditorContributionCtor[] { + return EditorContributionRegistry.INSTANCE.getDiffEditorContributions(); + } } // Editor extension points @@ -325,11 +334,13 @@ class EditorContributionRegistry { public static readonly INSTANCE = new EditorContributionRegistry(); private readonly editorContributions: IEditorContributionCtor[]; + private readonly diffEditorContributions: IDiffEditorContributionCtor[]; private readonly editorActions: EditorAction[]; private readonly editorCommands: { [commandId: string]: EditorCommand; }; constructor() { this.editorContributions = []; + this.diffEditorContributions = []; this.editorActions = []; this.editorCommands = Object.create(null); } @@ -338,15 +349,23 @@ class EditorContributionRegistry { this.editorContributions.push(ctor); } + public getEditorContributions(): IEditorContributionCtor[] { + return this.editorContributions.slice(0); + } + + public registerDiffEditorContribution(ctor: IDiffEditorContributionCtor): void { + this.diffEditorContributions.push(ctor); + } + + public getDiffEditorContributions(): IDiffEditorContributionCtor[] { + return this.diffEditorContributions.slice(0); + } + public registerEditorAction(action: EditorAction) { action.register(); this.editorActions.push(action); } - public getEditorContributions(): IEditorContributionCtor[] { - return this.editorContributions.slice(0); - } - public getEditorActions(): EditorAction[] { return this.editorActions.slice(0); } diff --git a/src/vs/editor/browser/viewParts/contentWidgets/contentWidgets.ts b/src/vs/editor/browser/viewParts/contentWidgets/contentWidgets.ts index eb49a439f9d..e98cea19e9c 100644 --- a/src/vs/editor/browser/viewParts/contentWidgets/contentWidgets.ts +++ b/src/vs/editor/browser/viewParts/contentWidgets/contentWidgets.ts @@ -9,7 +9,7 @@ import { ContentWidgetPositionPreference, IContentWidget } from 'vs/editor/brows import { PartFingerprint, PartFingerprints, ViewPart } from 'vs/editor/browser/view/viewPart'; import { IPosition, Position } from 'vs/editor/common/core/position'; import { IRange, Range } from 'vs/editor/common/core/range'; -import { Constants } from 'vs/editor/common/core/uint'; +import { Constants } from 'vs/base/common/uint'; import { RenderingContext, RestrictedRenderingContext } from 'vs/editor/common/view/renderingContext'; import { ViewContext } from 'vs/editor/common/view/viewContext'; import * as viewEvents from 'vs/editor/common/view/viewEvents'; diff --git a/src/vs/editor/browser/viewParts/lines/rangeUtil.ts b/src/vs/editor/browser/viewParts/lines/rangeUtil.ts index 5344effa706..f84a79df8d4 100644 --- a/src/vs/editor/browser/viewParts/lines/rangeUtil.ts +++ b/src/vs/editor/browser/viewParts/lines/rangeUtil.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { Constants } from 'vs/editor/common/core/uint'; +import { Constants } from 'vs/base/common/uint'; import { HorizontalRange } from 'vs/editor/common/view/renderingContext'; class FloatHorizontalRange { diff --git a/src/vs/editor/browser/viewParts/lines/viewLines.ts b/src/vs/editor/browser/viewParts/lines/viewLines.ts index eb524a41b69..ff3a504d5cf 100644 --- a/src/vs/editor/browser/viewParts/lines/viewLines.ts +++ b/src/vs/editor/browser/viewParts/lines/viewLines.ts @@ -20,6 +20,7 @@ import * as viewEvents from 'vs/editor/common/view/viewEvents'; import { ViewportData } from 'vs/editor/common/viewLayout/viewLinesViewportData'; import { Viewport } from 'vs/editor/common/viewModel/viewModel'; import { EditorOption } from 'vs/editor/common/config/editorOptions'; +import { Constants } from 'vs/base/common/uint'; class LastRenderedData { @@ -641,7 +642,7 @@ export class ViewLines extends ViewPart implements IVisibleLinesHost<ViewLine>, const viewportEndX = viewportStartX + viewport.width; const visibleRanges = this.visibleRangesForRange2(new Range(lineNumber, startColumn, lineNumber, endColumn)); - let boxStartX = Number.MAX_VALUE; + let boxStartX = Constants.MAX_SAFE_SMALL_INTEGER; let boxEndX = 0; if (!visibleRanges) { diff --git a/src/vs/editor/browser/widget/diffEditorWidget.ts b/src/vs/editor/browser/widget/diffEditorWidget.ts index d1bc2ad7820..1ac2ad30699 100644 --- a/src/vs/editor/browser/widget/diffEditorWidget.ts +++ b/src/vs/editor/browser/widget/diffEditorWidget.ts @@ -43,6 +43,9 @@ import { ITheme, IThemeService, getThemeTypeSelector, registerThemingParticipant import { IContextMenuService } from 'vs/platform/contextview/browser/contextView'; import { IDiffLinesChange, InlineDiffMargin } from 'vs/editor/browser/widget/inlineDiffMargin'; import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService'; +import { Constants } from 'vs/base/common/uint'; +import { IDiffEditorContributionCtor, EditorExtensionsRegistry } from 'vs/editor/browser/editorExtensions'; +import { onUnexpectedError } from 'vs/base/common/errors'; interface IEditorDiffDecorations { decorations: IModelDeltaDecoration[]; @@ -364,6 +367,15 @@ export class DiffEditorWidget extends Disposable implements editorBrowser.IDiffE this._containerDomElement.className = DiffEditorWidget._getClassName(this._themeService.getTheme(), this._renderSideBySide); })); + const contributions: IDiffEditorContributionCtor[] = EditorExtensionsRegistry.getDiffEditorContributions(); + for (const ctor of contributions) { + try { + this._register(instantiationService.createInstance(ctor, this)); + } catch (err) { + onUnexpectedError(err); + } + } + this._codeEditorService.addDiffEditor(this); } @@ -491,6 +503,12 @@ export class DiffEditorWidget extends Disposable implements editorBrowser.IDiffE } })); + this._register(editor.onDidChangeModelOptions((e) => { + if (e.tabSize) { + this._updateDecorationsRunner.schedule(); + } + })); + return editor; } @@ -560,6 +578,10 @@ export class DiffEditorWidget extends Disposable implements editorBrowser.IDiffE return this._diffComputationResult.changes; } + public getDiffComputationResult(): IDiffComputationResult | null { + return this._diffComputationResult; + } + public getOriginalEditor(): editorBrowser.ICodeEditor { return this.originalEditor; } @@ -646,6 +668,8 @@ export class DiffEditorWidget extends Disposable implements editorBrowser.IDiffE this.modifiedEditor.setModel(model ? model.modified : null); this._updateDecorationsRunner.cancel(); + // this.originalEditor.onDidChangeModelOptions + if (model) { this.originalEditor.setScrollTop(0); this.modifiedEditor.setScrollTop(0); @@ -989,7 +1013,6 @@ export class DiffEditorWidget extends Disposable implements editorBrowser.IDiffE private _adjustOptionsForLeftHandSide(options: IDiffEditorOptions, isEditable: boolean): IEditorOptions { let result = this._adjustOptionsForSubEditor(options); result.readOnly = !isEditable; - result.overviewRulerLanes = 1; result.extraEditorClassName = 'original-in-monaco-diff-editor'; return result; } @@ -1122,7 +1145,7 @@ export class DiffEditorWidget extends Disposable implements editorBrowser.IDiffE while (min < max) { let mid = Math.floor((min + max) / 2); let midStart = startLineNumberExtractor(lineChanges[mid]); - let midEnd = (mid + 1 <= max ? startLineNumberExtractor(lineChanges[mid + 1]) : Number.MAX_VALUE); + let midEnd = (mid + 1 <= max ? startLineNumberExtractor(lineChanges[mid + 1]) : Constants.MAX_SAFE_SMALL_INTEGER); if (lineNumber < midStart) { max = mid - 1; @@ -1682,11 +1705,11 @@ class DiffEditorWidgetSideBySide extends DiffEditorWidgetStyle implements IDiffE if (isChangeOrDelete(lineChange)) { result.decorations.push({ - range: new Range(lineChange.originalStartLineNumber, 1, lineChange.originalEndLineNumber, Number.MAX_VALUE), + range: new Range(lineChange.originalStartLineNumber, 1, lineChange.originalEndLineNumber, Constants.MAX_SAFE_SMALL_INTEGER), options: (renderIndicators ? DECORATIONS.lineDeleteWithSign : DECORATIONS.lineDelete) }); if (!isChangeOrInsert(lineChange) || !lineChange.charChanges) { - result.decorations.push(createDecoration(lineChange.originalStartLineNumber, 1, lineChange.originalEndLineNumber, Number.MAX_VALUE, DECORATIONS.charDeleteWholeLine)); + result.decorations.push(createDecoration(lineChange.originalStartLineNumber, 1, lineChange.originalEndLineNumber, Constants.MAX_SAFE_SMALL_INTEGER, DECORATIONS.charDeleteWholeLine)); } result.overviewZones.push(new OverviewRulerZone( @@ -1743,11 +1766,11 @@ class DiffEditorWidgetSideBySide extends DiffEditorWidgetStyle implements IDiffE if (isChangeOrInsert(lineChange)) { result.decorations.push({ - range: new Range(lineChange.modifiedStartLineNumber, 1, lineChange.modifiedEndLineNumber, Number.MAX_VALUE), + range: new Range(lineChange.modifiedStartLineNumber, 1, lineChange.modifiedEndLineNumber, Constants.MAX_SAFE_SMALL_INTEGER), options: (renderIndicators ? DECORATIONS.lineInsertWithSign : DECORATIONS.lineInsert) }); if (!isChangeOrDelete(lineChange) || !lineChange.charChanges) { - result.decorations.push(createDecoration(lineChange.modifiedStartLineNumber, 1, lineChange.modifiedEndLineNumber, Number.MAX_VALUE, DECORATIONS.charInsertWholeLine)); + result.decorations.push(createDecoration(lineChange.modifiedStartLineNumber, 1, lineChange.modifiedEndLineNumber, Constants.MAX_SAFE_SMALL_INTEGER, DECORATIONS.charInsertWholeLine)); } result.overviewZones.push(new OverviewRulerZone( lineChange.modifiedStartLineNumber, @@ -1861,7 +1884,7 @@ class DiffEditorWidgetInline extends DiffEditorWidgetStyle implements IDiffEdito // Add overview zones in the overview ruler if (isChangeOrDelete(lineChange)) { result.decorations.push({ - range: new Range(lineChange.originalStartLineNumber, 1, lineChange.originalEndLineNumber, Number.MAX_VALUE), + range: new Range(lineChange.originalStartLineNumber, 1, lineChange.originalEndLineNumber, Constants.MAX_SAFE_SMALL_INTEGER), options: DECORATIONS.lineDeleteMargin }); @@ -1892,7 +1915,7 @@ class DiffEditorWidgetInline extends DiffEditorWidgetStyle implements IDiffEdito // Add decorations & overview zones if (isChangeOrInsert(lineChange)) { result.decorations.push({ - range: new Range(lineChange.modifiedStartLineNumber, 1, lineChange.modifiedEndLineNumber, Number.MAX_VALUE), + range: new Range(lineChange.modifiedStartLineNumber, 1, lineChange.modifiedEndLineNumber, Constants.MAX_SAFE_SMALL_INTEGER), options: (renderIndicators ? DECORATIONS.lineInsertWithSign : DECORATIONS.lineInsert) }); @@ -1928,7 +1951,7 @@ class DiffEditorWidgetInline extends DiffEditorWidgetStyle implements IDiffEdito } } } else { - result.decorations.push(createDecoration(lineChange.modifiedStartLineNumber, 1, lineChange.modifiedEndLineNumber, Number.MAX_VALUE, DECORATIONS.charInsertWholeLine)); + result.decorations.push(createDecoration(lineChange.modifiedStartLineNumber, 1, lineChange.modifiedEndLineNumber, Constants.MAX_SAFE_SMALL_INTEGER, DECORATIONS.charInsertWholeLine)); } } } diff --git a/src/vs/editor/common/config/editorOptions.ts b/src/vs/editor/common/config/editorOptions.ts index 2b39a750360..44a7959ddcf 100644 --- a/src/vs/editor/common/config/editorOptions.ts +++ b/src/vs/editor/common/config/editorOptions.ts @@ -7,7 +7,7 @@ import * as nls from 'vs/nls'; import * as platform from 'vs/base/common/platform'; import { ScrollbarVisibility } from 'vs/base/common/scrollable'; import { FontInfo } from 'vs/editor/common/config/fontInfo'; -import { Constants } from 'vs/editor/common/core/uint'; +import { Constants } from 'vs/base/common/uint'; import { USUAL_WORD_SEPARATORS } from 'vs/editor/common/model/wordHelper'; import { AccessibilitySupport } from 'vs/platform/accessibility/common/accessibility'; import { isObject } from 'vs/base/common/types'; diff --git a/src/vs/editor/common/core/characterClassifier.ts b/src/vs/editor/common/core/characterClassifier.ts index 9d448641d17..214bb2abf05 100644 --- a/src/vs/editor/common/core/characterClassifier.ts +++ b/src/vs/editor/common/core/characterClassifier.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { toUint8 } from 'vs/editor/common/core/uint'; +import { toUint8 } from 'vs/base/common/uint'; /** * A fast character classifier that uses a compact array for ASCII values. diff --git a/src/vs/editor/common/editorCommon.ts b/src/vs/editor/common/editorCommon.ts index 066559ab3cc..40404a20106 100644 --- a/src/vs/editor/common/editorCommon.ts +++ b/src/vs/editor/common/editorCommon.ts @@ -507,6 +507,21 @@ export interface IEditorContribution { } /** + * A diff editor contribution that gets created every time a new diffeditor gets created and gets disposed when the diff editor gets disposed. + * @internal + */ +export interface IDiffEditorContribution { + /** + * Get a unique identifier for this contribution. + */ + getId(): string; + /** + * Dispose this contribution. + */ + dispose(): void; +} + +/** * @internal */ export function isThemeColor(o: any): o is ThemeColor { diff --git a/src/vs/editor/common/modes/linkComputer.ts b/src/vs/editor/common/modes/linkComputer.ts index 00bf7d01b36..6673c04f64a 100644 --- a/src/vs/editor/common/modes/linkComputer.ts +++ b/src/vs/editor/common/modes/linkComputer.ts @@ -5,7 +5,6 @@ import { CharCode } from 'vs/base/common/charCode'; import { CharacterClassifier } from 'vs/editor/common/core/characterClassifier'; -import { Uint8Matrix } from 'vs/editor/common/core/uint'; import { ILink } from 'vs/editor/common/modes'; export interface ILinkComputerTarget { @@ -33,6 +32,32 @@ export const enum State { export type Edge = [State, number, State]; +export class Uint8Matrix { + + private readonly _data: Uint8Array; + public readonly rows: number; + public readonly cols: number; + + constructor(rows: number, cols: number, defaultValue: number) { + const data = new Uint8Array(rows * cols); + for (let i = 0, len = rows * cols; i < len; i++) { + data[i] = defaultValue; + } + + this._data = data; + this.rows = rows; + this.cols = cols; + } + + public get(row: number, col: number): number { + return this._data[row * this.cols + col]; + } + + public set(row: number, col: number, value: number): void { + this._data[row * this.cols + col] = value; + } +} + export class StateMachine { private readonly _states: Uint8Matrix; diff --git a/src/vs/editor/common/services/editorSimpleWorker.ts b/src/vs/editor/common/services/editorSimpleWorker.ts index 06c11b3303e..682f1e9bf89 100644 --- a/src/vs/editor/common/services/editorSimpleWorker.ts +++ b/src/vs/editor/common/services/editorSimpleWorker.ts @@ -377,11 +377,11 @@ export class EditorSimpleWorker implements IRequestHandler, IDisposable { // ---- BEGIN diff -------------------------------------------------------------------------- - public computeDiff(originalUrl: string, modifiedUrl: string, ignoreTrimWhitespace: boolean): Promise<IDiffComputationResult | null> { + public async computeDiff(originalUrl: string, modifiedUrl: string, ignoreTrimWhitespace: boolean): Promise<IDiffComputationResult | null> { const original = this._getModel(originalUrl); const modified = this._getModel(modifiedUrl); if (!original || !modified) { - return Promise.resolve(null); + return null; } const originalLines = original.getLinesContent(); @@ -395,10 +395,10 @@ export class EditorSimpleWorker implements IRequestHandler, IDisposable { const changes = diffComputer.computeDiff(); let identical = (changes.length > 0 ? false : this._modelsAreIdentical(original, modified)); - return Promise.resolve({ + return { identical: identical, changes: changes - }); + }; } private _modelsAreIdentical(original: ICommonModel, modified: ICommonModel): boolean { @@ -417,11 +417,11 @@ export class EditorSimpleWorker implements IRequestHandler, IDisposable { return true; } - public computeDirtyDiff(originalUrl: string, modifiedUrl: string, ignoreTrimWhitespace: boolean): Promise<editorCommon.IChange[] | null> { + public async computeDirtyDiff(originalUrl: string, modifiedUrl: string, ignoreTrimWhitespace: boolean): Promise<editorCommon.IChange[] | null> { let original = this._getModel(originalUrl); let modified = this._getModel(modifiedUrl); if (!original || !modified) { - return Promise.resolve(null); + return null; } let originalLines = original.getLinesContent(); @@ -432,7 +432,7 @@ export class EditorSimpleWorker implements IRequestHandler, IDisposable { shouldIgnoreTrimWhitespace: ignoreTrimWhitespace, shouldMakePrettyDiff: true }); - return Promise.resolve(diffComputer.computeDiff()); + return diffComputer.computeDiff(); } // ---- END diff -------------------------------------------------------------------------- @@ -442,10 +442,10 @@ export class EditorSimpleWorker implements IRequestHandler, IDisposable { private static readonly _diffLimit = 100000; - public computeMoreMinimalEdits(modelUrl: string, edits: TextEdit[]): Promise<TextEdit[]> { + public async computeMoreMinimalEdits(modelUrl: string, edits: TextEdit[]): Promise<TextEdit[]> { const model = this._getModel(modelUrl); if (!model) { - return Promise.resolve(edits); + return edits; } const result: TextEdit[] = []; @@ -508,28 +508,28 @@ export class EditorSimpleWorker implements IRequestHandler, IDisposable { result.push({ eol: lastEol, text: '', range: { startLineNumber: 0, startColumn: 0, endLineNumber: 0, endColumn: 0 } }); } - return Promise.resolve(result); + return result; } // ---- END minimal edits --------------------------------------------------------------- - public computeLinks(modelUrl: string): Promise<ILink[] | null> { + public async computeLinks(modelUrl: string): Promise<ILink[] | null> { let model = this._getModel(modelUrl); if (!model) { - return Promise.resolve(null); + return null; } - return Promise.resolve(computeLinks(model)); + return computeLinks(model); } // ---- BEGIN suggest -------------------------------------------------------------------------- private static readonly _suggestionsLimit = 10000; - public textualSuggest(modelUrl: string, position: IPosition, wordDef: string, wordDefFlags: string): Promise<CompletionList | null> { + public async textualSuggest(modelUrl: string, position: IPosition, wordDef: string, wordDefFlags: string): Promise<CompletionList | null> { const model = this._getModel(modelUrl); if (!model) { - return Promise.resolve(null); + return null; } const seen: Record<string, boolean> = Object.create(null); @@ -563,7 +563,7 @@ export class EditorSimpleWorker implements IRequestHandler, IDisposable { range: { startLineNumber: position.lineNumber, startColumn: wordUntil.startColumn, endLineNumber: position.lineNumber, endColumn: wordUntil.endColumn } }); } - return Promise.resolve({ suggestions }); + return { suggestions }; } @@ -571,10 +571,10 @@ export class EditorSimpleWorker implements IRequestHandler, IDisposable { //#region -- word ranges -- - computeWordRanges(modelUrl: string, range: IRange, wordDef: string, wordDefFlags: string): Promise<{ [word: string]: IRange[] }> { + public async computeWordRanges(modelUrl: string, range: IRange, wordDef: string, wordDefFlags: string): Promise<{ [word: string]: IRange[] }> { let model = this._getModel(modelUrl); if (!model) { - return Promise.resolve(Object.create(null)); + return Object.create(null); } const wordDefRegExp = new RegExp(wordDef, wordDefFlags); const result: { [word: string]: IRange[] } = Object.create(null); @@ -597,15 +597,15 @@ export class EditorSimpleWorker implements IRequestHandler, IDisposable { }); } } - return Promise.resolve(result); + return result; } //#endregion - public navigateValueSet(modelUrl: string, range: IRange, up: boolean, wordDef: string, wordDefFlags: string): Promise<IInplaceReplaceSupportResult | null> { + public async navigateValueSet(modelUrl: string, range: IRange, up: boolean, wordDef: string, wordDefFlags: string): Promise<IInplaceReplaceSupportResult | null> { let model = this._getModel(modelUrl); if (!model) { - return Promise.resolve(null); + return null; } let wordDefRegExp = new RegExp(wordDef, wordDefFlags); @@ -623,11 +623,11 @@ export class EditorSimpleWorker implements IRequestHandler, IDisposable { let wordRange = model.getWordAtPosition({ lineNumber: range.startLineNumber, column: range.startColumn }, wordDefRegExp); if (!wordRange) { - return Promise.resolve(null); + return null; } let word = model.getValueInRange(wordRange); let result = BasicInplaceReplace.INSTANCE.navigateValueSet(range, selectionText, wordRange, word, up); - return Promise.resolve(result); + return result; } // ---- BEGIN foreign module support -------------------------------------------------------------------------- diff --git a/src/vs/editor/common/viewLayout/lineDecorations.ts b/src/vs/editor/common/viewLayout/lineDecorations.ts index cae03bc9e46..a384c18a977 100644 --- a/src/vs/editor/common/viewLayout/lineDecorations.ts +++ b/src/vs/editor/common/viewLayout/lineDecorations.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import * as strings from 'vs/base/common/strings'; -import { Constants } from 'vs/editor/common/core/uint'; +import { Constants } from 'vs/base/common/uint'; import { InlineDecoration, InlineDecorationType } from 'vs/editor/common/viewModel/viewModel'; import { equals } from 'vs/base/common/arrays'; diff --git a/src/vs/editor/common/viewModel/characterHardWrappingLineMapper.ts b/src/vs/editor/common/viewModel/characterHardWrappingLineMapper.ts index 74b236d4b78..bbf71e817b9 100644 --- a/src/vs/editor/common/viewModel/characterHardWrappingLineMapper.ts +++ b/src/vs/editor/common/viewModel/characterHardWrappingLineMapper.ts @@ -7,7 +7,7 @@ import { CharCode } from 'vs/base/common/charCode'; import * as strings from 'vs/base/common/strings'; import { WrappingIndent } from 'vs/editor/common/config/editorOptions'; import { CharacterClassifier } from 'vs/editor/common/core/characterClassifier'; -import { toUint32Array } from 'vs/editor/common/core/uint'; +import { toUint32Array } from 'vs/base/common/uint'; import { PrefixSumComputer } from 'vs/editor/common/viewModel/prefixSumComputer'; import { ILineMapperFactory, ILineMapping, OutputPosition } from 'vs/editor/common/viewModel/splitLinesCollection'; diff --git a/src/vs/editor/common/viewModel/prefixSumComputer.ts b/src/vs/editor/common/viewModel/prefixSumComputer.ts index 81e66ac5059..d4e8c1f0df2 100644 --- a/src/vs/editor/common/viewModel/prefixSumComputer.ts +++ b/src/vs/editor/common/viewModel/prefixSumComputer.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { toUint32 } from 'vs/editor/common/core/uint'; +import { toUint32 } from 'vs/base/common/uint'; export class PrefixSumIndexOfResult { _prefixSumIndexOfResultBrand: void; diff --git a/src/vs/editor/contrib/codeAction/codeActionCommands.ts b/src/vs/editor/contrib/codeAction/codeActionCommands.ts index 07f52a6ed51..0a516e15d76 100644 --- a/src/vs/editor/contrib/codeAction/codeActionCommands.ts +++ b/src/vs/editor/contrib/codeAction/codeActionCommands.ts @@ -68,7 +68,7 @@ export class QuickFixController extends Disposable implements IEditorContributio this._register(this._model.onDidChangeState(newState => this.update(newState))); this._ui = new Lazy(() => - this._register(new CodeActionUi(editor, QuickFixAction.Id, { + this._register(new CodeActionUi(editor, QuickFixAction.Id, AutoFixAction.Id, { applyCodeAction: async (action, retrigger) => { try { await this._applyCodeAction(action); diff --git a/src/vs/editor/contrib/codeAction/codeActionUi.ts b/src/vs/editor/contrib/codeAction/codeActionUi.ts index 658aebe8e3a..67edd66106c 100644 --- a/src/vs/editor/contrib/codeAction/codeActionUi.ts +++ b/src/vs/editor/contrib/codeAction/codeActionUi.ts @@ -28,6 +28,7 @@ export class CodeActionUi extends Disposable { constructor( private readonly _editor: ICodeEditor, quickFixActionId: string, + preferredFixActionId: string, private readonly delegate: { applyCodeAction: (action: CodeAction, regtriggerAfterApply: boolean) => void }, @@ -45,7 +46,7 @@ export class CodeActionUi extends Disposable { }); this._lightBulbWidget = new Lazy(() => { - const widget = this._register(new LightBulbWidget(this._editor, quickFixActionId, keybindingService)); + const widget = this._register(new LightBulbWidget(this._editor, quickFixActionId, preferredFixActionId, keybindingService)); this._register(widget.onClick(this._handleLightBulbSelect, this)); return widget; }); diff --git a/src/vs/editor/contrib/codeAction/lightBulbWidget.ts b/src/vs/editor/contrib/codeAction/lightBulbWidget.ts index 8c5f26d3668..505f13244f9 100644 --- a/src/vs/editor/contrib/codeAction/lightBulbWidget.ts +++ b/src/vs/editor/contrib/codeAction/lightBulbWidget.ts @@ -47,7 +47,7 @@ export class LightBulbWidget extends Disposable implements IContentWidget { private readonly _domNode: HTMLDivElement; - private readonly _onClick = this._register(new Emitter<{ x: number; y: number; actions: CodeActionSet }>()); + private readonly _onClick = this._register(new Emitter<{ x: number; y: number; actions: CodeActionSet; }>()); public readonly onClick = this._onClick.event; private _state: LightBulbState.State = LightBulbState.Hidden; @@ -55,6 +55,7 @@ export class LightBulbWidget extends Disposable implements IContentWidget { constructor( private readonly _editor: ICodeEditor, private readonly _quickFixActionId: string, + private readonly _preferredFixActionId: string, @IKeybindingService private readonly _keybindingService: IKeybindingService ) { super(); @@ -66,12 +67,12 @@ export class LightBulbWidget extends Disposable implements IContentWidget { this._register(this._editor.onDidChangeModelContent(_ => { // cancel when the line in question has been removed const editorModel = this._editor.getModel(); - if (this._state.type !== LightBulbState.Type.Showing || !editorModel || this._state.editorPosition.lineNumber >= editorModel.getLineCount()) { + if (this.state.type !== LightBulbState.Type.Showing || !editorModel || this.state.editorPosition.lineNumber >= editorModel.getLineCount()) { this.hide(); } })); this._register(dom.addStandardDisposableListener(this._domNode, 'mousedown', e => { - if (this._state.type !== LightBulbState.Type.Showing) { + if (this.state.type !== LightBulbState.Type.Showing) { return; } @@ -84,14 +85,14 @@ export class LightBulbWidget extends Disposable implements IContentWidget { const lineHeight = this._editor.getOption(EditorOption.lineHeight); let pad = Math.floor(lineHeight / 3); - if (this._state.widgetPosition.position !== null && this._state.widgetPosition.position.lineNumber < this._state.editorPosition.lineNumber) { + if (this.state.widgetPosition.position !== null && this.state.widgetPosition.position.lineNumber < this.state.editorPosition.lineNumber) { pad += lineHeight; } this._onClick.fire({ x: e.posx, y: top + height + pad, - actions: this._state.actions + actions: this.state.actions }); })); this._register(dom.addDisposableListener(this._domNode, 'mouseenter', (e: MouseEvent) => { @@ -173,7 +174,7 @@ export class LightBulbWidget extends Disposable implements IContentWidget { } } - this._state = new LightBulbState.Showing(actions, atPosition, { + this.state = new LightBulbState.Showing(actions, atPosition, { position: { lineNumber: effectiveLineNumber, column: 1 }, preference: LightBulbWidget._posPref }); @@ -181,24 +182,37 @@ export class LightBulbWidget extends Disposable implements IContentWidget { this._editor.layoutContentWidget(this); } - private set title(value: string) { - this._domNode.title = value; - } - public hide(): void { - this._state = LightBulbState.Hidden; + this.state = LightBulbState.Hidden; this._editor.layoutContentWidget(this); } + private get state(): LightBulbState.State { return this._state; } + + private set state(value) { + this._state = value; + this._updateLightBulbTitle(); + } + private _updateLightBulbTitle(): void { + if (this.state.type === LightBulbState.Type.Showing && this.state.actions.hasAutoFix) { + const preferredKb = this._keybindingService.lookupKeybinding(this._preferredFixActionId); + if (preferredKb) { + this.title = nls.localize('prefferedQuickFixWithKb', "Show Fixes. Preferred Fix Available ({0})", preferredKb.getLabel()); + return; + } + } + const kb = this._keybindingService.lookupKeybinding(this._quickFixActionId); - let title: string; if (kb) { - title = nls.localize('quickFixWithKb', "Show Fixes ({0})", kb.getLabel()); + this.title = nls.localize('quickFixWithKb', "Show Fixes ({0})", kb.getLabel()); } else { - title = nls.localize('quickFix', "Show Fixes"); + this.title = nls.localize('quickFix', "Show Fixes"); } - this.title = title; + } + + private set title(value: string) { + this._domNode.title = value; } } diff --git a/src/vs/editor/contrib/comment/lineCommentCommand.ts b/src/vs/editor/contrib/comment/lineCommentCommand.ts index a097d994648..5c3716ed79c 100644 --- a/src/vs/editor/contrib/comment/lineCommentCommand.ts +++ b/src/vs/editor/contrib/comment/lineCommentCommand.ts @@ -13,6 +13,7 @@ import * as editorCommon from 'vs/editor/common/editorCommon'; import { IIdentifiedSingleEditOperation, ITextModel } from 'vs/editor/common/model'; import { LanguageConfigurationRegistry } from 'vs/editor/common/modes/languageConfigurationRegistry'; import { BlockCommentCommand } from 'vs/editor/contrib/comment/blockCommentCommand'; +import { Constants } from 'vs/base/common/uint'; export interface IInsertionPoint { ignore: boolean; @@ -392,7 +393,7 @@ export class LineCommentCommand implements editorCommon.ICommand { * Adjust insertion points to have them vertically aligned in the add line comment case */ public static _normalizeInsertionPoint(model: ISimpleModel, lines: IInsertionPoint[], startLineNumber: number, tabSize: number): void { - let minVisibleColumn = Number.MAX_VALUE; + let minVisibleColumn = Constants.MAX_SAFE_SMALL_INTEGER; let j: number; let lenJ: number; diff --git a/src/vs/editor/contrib/find/findModel.ts b/src/vs/editor/contrib/find/findModel.ts index e039801431f..da67f86eb78 100644 --- a/src/vs/editor/contrib/find/findModel.ts +++ b/src/vs/editor/contrib/find/findModel.ts @@ -12,7 +12,7 @@ import { CursorChangeReason, ICursorPositionChangedEvent } from 'vs/editor/commo import { Position } from 'vs/editor/common/core/position'; import { Range } from 'vs/editor/common/core/range'; import { Selection } from 'vs/editor/common/core/selection'; -import { Constants } from 'vs/editor/common/core/uint'; +import { Constants } from 'vs/base/common/uint'; import * as editorCommon from 'vs/editor/common/editorCommon'; import { EndOfLinePreference, FindMatch, ITextModel } from 'vs/editor/common/model'; import { SearchParams } from 'vs/editor/common/model/textModelSearch'; diff --git a/src/vs/editor/contrib/hover/modesContentHover.ts b/src/vs/editor/contrib/hover/modesContentHover.ts index 06877b671d5..8dae61e55d0 100644 --- a/src/vs/editor/contrib/hover/modesContentHover.ts +++ b/src/vs/editor/contrib/hover/modesContentHover.ts @@ -38,6 +38,7 @@ import { CodeActionKind } from 'vs/editor/contrib/codeAction/codeActionTrigger'; import { IModeService } from 'vs/editor/common/services/modeService'; import { IIdentifiedSingleEditOperation } from 'vs/editor/common/model'; import { EditorOption } from 'vs/editor/common/config/editorOptions'; +import { Constants } from 'vs/base/common/uint'; const $ = dom.$; @@ -333,7 +334,7 @@ export class ModesContentHoverWidget extends ContentHoverWidget { this._colorPicker = null; // update column from which to show - let renderColumn = Number.MAX_VALUE; + let renderColumn = Constants.MAX_SAFE_SMALL_INTEGER; let highlightRange: Range | null = messages[0].range ? Range.lift(messages[0].range) : null; let fragment = document.createDocumentFragment(); let isEmptyHoverContent = true; diff --git a/src/vs/editor/contrib/multicursor/multicursor.ts b/src/vs/editor/contrib/multicursor/multicursor.ts index a76a1d62e96..11516c57f83 100644 --- a/src/vs/editor/contrib/multicursor/multicursor.ts +++ b/src/vs/editor/contrib/multicursor/multicursor.ts @@ -14,7 +14,7 @@ import { CursorChangeReason, ICursorSelectionChangedEvent } from 'vs/editor/comm import { CursorMoveCommands } from 'vs/editor/common/controller/cursorMoveCommands'; import { Range } from 'vs/editor/common/core/range'; import { Selection } from 'vs/editor/common/core/selection'; -import { Constants } from 'vs/editor/common/core/uint'; +import { Constants } from 'vs/base/common/uint'; import { IEditorContribution, ScrollType } from 'vs/editor/common/editorCommon'; import { EditorContextKeys } from 'vs/editor/common/editorContextKeys'; import { FindMatch, ITextModel, OverviewRulerLane, TrackedRangeStickiness } from 'vs/editor/common/model'; diff --git a/src/vs/editor/contrib/referenceSearch/referencesModel.ts b/src/vs/editor/contrib/referenceSearch/referencesModel.ts index 36d54e60852..579625ed01d 100644 --- a/src/vs/editor/contrib/referenceSearch/referencesModel.ts +++ b/src/vs/editor/contrib/referenceSearch/referencesModel.ts @@ -15,6 +15,7 @@ import { Location, LocationLink } from 'vs/editor/common/modes'; import { ITextModelService, ITextEditorModel } from 'vs/editor/common/services/resolverService'; import { Position } from 'vs/editor/common/core/position'; import { IMatch } from 'vs/base/common/filters'; +import { Constants } from 'vs/base/common/uint'; export class OneReference { readonly id: string; @@ -72,7 +73,7 @@ export class FilePreview implements IDisposable { const { startLineNumber, startColumn, endLineNumber, endColumn } = range; const word = model.getWordUntilPosition({ lineNumber: startLineNumber, column: startColumn - n }); const beforeRange = new Range(startLineNumber, word.startColumn, startLineNumber, startColumn); - const afterRange = new Range(endLineNumber, endColumn, endLineNumber, Number.MAX_VALUE); + const afterRange = new Range(endLineNumber, endColumn, endLineNumber, Constants.MAX_SAFE_SMALL_INTEGER); const before = model.getValueInRange(beforeRange).replace(/^\s+/, ''); const inside = model.getValueInRange(range); diff --git a/src/vs/editor/contrib/suggest/suggestController.ts b/src/vs/editor/contrib/suggest/suggestController.ts index b8cb308422c..1ae5015e015 100644 --- a/src/vs/editor/contrib/suggest/suggestController.ts +++ b/src/vs/editor/contrib/suggest/suggestController.ts @@ -242,8 +242,7 @@ export class SuggestController implements IEditorContribution { const model = this._editor.getModel(); const modelVersionNow = model.getAlternativeVersionId(); const { completion: suggestion, position } = event.item; - const editorPosition = this._editor.getPosition(); - const columnDelta = editorPosition.column - position.column; + const columnDelta = this._editor.getPosition().column - position.column; // pushing undo stops *before* additional text edits and // *after* the main edit @@ -256,7 +255,7 @@ export class SuggestController implements IEditorContribution { } // keep item in memory - this._memoryService.memorize(model, editorPosition, event.item); + this._memoryService.memorize(model, this._editor.getPosition(), event.item); let { insertText } = suggestion; if (!(suggestion.insertTextRules! & CompletionItemInsertTextRule.InsertAsSnippet)) { @@ -265,7 +264,7 @@ export class SuggestController implements IEditorContribution { let overwriteBefore = position.column - suggestion.range.startColumn; let overwriteAfter = suggestion.range.endColumn - position.column; - let suffixDelta = this._lineSuffix.value ? this._lineSuffix.value.delta(editorPosition) : 0; + let suffixDelta = this._lineSuffix.value ? this._lineSuffix.value.delta(this._editor.getPosition()) : 0; let word: IWordAtPosition | null; if (!keepSuffix) { // don't overwrite anything right of the cursor @@ -273,7 +272,7 @@ export class SuggestController implements IEditorContribution { } else if (overwriteAfter === 0 && (word = model.getWordAtPosition(position))) { // compute fallback overwrite length - overwriteAfter = word.endColumn - editorPosition.column; + overwriteAfter = word.endColumn - this._editor.getPosition().column; } SnippetController2.get(this._editor).insert(insertText, { diff --git a/src/vs/editor/contrib/suggest/suggestWidget.ts b/src/vs/editor/contrib/suggest/suggestWidget.ts index 418d07d5b57..8abaf62c4af 100644 --- a/src/vs/editor/contrib/suggest/suggestWidget.ts +++ b/src/vs/editor/contrib/suggest/suggestWidget.ts @@ -174,10 +174,9 @@ class Renderer implements IListRenderer<CompletionItem, ISuggestionTemplateData> } else if (suggestion.kind === CompletionItemKind.File && this._themeService.getIconTheme().hasFileIcons) { // special logic for 'file' completion items data.icon.className = 'icon hide'; - labelOptions.extraClasses = flatten([ - getIconClasses(this._modelService, this._modeService, URI.from({ scheme: 'fake', path: suggestion.label }), FileKind.FILE), - getIconClasses(this._modelService, this._modeService, URI.from({ scheme: 'fake', path: suggestion.detail }), FileKind.FILE) - ]); + const labelClasses = getIconClasses(this._modelService, this._modeService, URI.from({ scheme: 'fake', path: suggestion.label }), FileKind.FILE); + const detailClasses = getIconClasses(this._modelService, this._modeService, URI.from({ scheme: 'fake', path: suggestion.detail }), FileKind.FILE); + labelOptions.extraClasses = labelClasses.length > detailClasses.length ? labelClasses : detailClasses; } else if (suggestion.kind === CompletionItemKind.Folder && this._themeService.getIconTheme().hasFolderIcons) { // special logic for 'folder' completion items diff --git a/src/vs/editor/contrib/zoneWidget/zoneWidget.ts b/src/vs/editor/contrib/zoneWidget/zoneWidget.ts index f464b2b14f3..6a0346a2137 100644 --- a/src/vs/editor/contrib/zoneWidget/zoneWidget.ts +++ b/src/vs/editor/contrib/zoneWidget/zoneWidget.ts @@ -50,11 +50,11 @@ const WIDGET_ID = 'vs.editor.contrib.zoneWidget'; export class ViewZoneDelegate implements IViewZone { - public domNode: HTMLElement; - public id: string = ''; // A valid zone id should be greater than 0 - public afterLineNumber: number; - public afterColumn: number; - public heightInLines: number; + domNode: HTMLElement; + id: string = ''; // A valid zone id should be greater than 0 + afterLineNumber: number; + afterColumn: number; + heightInLines: number; private readonly _onDomNodeTop: (top: number) => void; private readonly _onComputedHeight: (height: number) => void; @@ -71,11 +71,11 @@ export class ViewZoneDelegate implements IViewZone { this._onComputedHeight = onComputedHeight; } - public onDomNodeTop(top: number): void { + onDomNodeTop(top: number): void { this._onDomNodeTop(top); } - public onComputedHeight(height: number): void { + onComputedHeight(height: number): void { this._onComputedHeight(height); } } @@ -90,15 +90,15 @@ export class OverlayWidgetDelegate implements IOverlayWidget { this._domNode = domNode; } - public getId(): string { + getId(): string { return this._id; } - public getDomNode(): HTMLElement { + getDomNode(): HTMLElement { return this._domNode; } - public getPosition(): IOverlayWidgetPosition | null { + getPosition(): IOverlayWidgetPosition | null { return null; } } @@ -167,10 +167,10 @@ export abstract class ZoneWidget implements IHorizontalSashLayoutProvider { protected _viewZone: ViewZoneDelegate | null = null; protected readonly _disposables = new DisposableStore(); - public container: HTMLElement | null = null; - public domNode: HTMLElement; - public editor: ICodeEditor; - public options: IOptions; + container: HTMLElement | null = null; + domNode: HTMLElement; + editor: ICodeEditor; + options: IOptions; constructor(editor: ICodeEditor, options: IOptions = {}) { @@ -191,7 +191,7 @@ export abstract class ZoneWidget implements IHorizontalSashLayoutProvider { })); } - public dispose(): void { + dispose(): void { if (this._overlayWidget) { this.editor.removeOverlayWidget(this._overlayWidget); this._overlayWidget = null; @@ -212,7 +212,7 @@ export abstract class ZoneWidget implements IHorizontalSashLayoutProvider { this._disposables.dispose(); } - public create(): void { + create(): void { dom.addClass(this.domNode, 'zone-widget'); if (this.options.className) { @@ -231,7 +231,7 @@ export abstract class ZoneWidget implements IHorizontalSashLayoutProvider { this._applyStyles(); } - public style(styles: IStyles): void { + style(styles: IStyles): void { if (styles.frameColor) { this.options.frameColor = styles.frameColor; } @@ -284,7 +284,7 @@ export abstract class ZoneWidget implements IHorizontalSashLayoutProvider { } } - public get position(): Position | undefined { + get position(): Position | undefined { const [id] = this._positionMarkerId; if (!id) { return undefined; @@ -304,18 +304,15 @@ export abstract class ZoneWidget implements IHorizontalSashLayoutProvider { protected _isShowing: boolean = false; - public show(rangeOrPos: IRange | IPosition, heightInLines: number): void { - const range = Range.isIRange(rangeOrPos) - ? rangeOrPos - : new Range(rangeOrPos.lineNumber, rangeOrPos.column, rangeOrPos.lineNumber, rangeOrPos.column); - + show(rangeOrPos: IRange | IPosition, heightInLines: number): void { + const range = Range.isIRange(rangeOrPos) ? Range.lift(rangeOrPos) : Range.fromPositions(rangeOrPos); this._isShowing = true; this._showImpl(range, heightInLines); this._isShowing = false; this._positionMarkerId = this.editor.deltaDecorations(this._positionMarkerId, [{ range, options: ModelDecorationOptions.EMPTY }]); } - public hide(): void { + hide(): void { if (this._viewZone) { this.editor.changeViewZones(accessor => { if (this._viewZone) { @@ -350,12 +347,8 @@ export abstract class ZoneWidget implements IHorizontalSashLayoutProvider { return result; } - private _showImpl(where: IRange, heightInLines: number): void { - const position = { - lineNumber: where.startLineNumber, - column: where.startColumn - }; - + private _showImpl(where: Range, heightInLines: number): void { + const position = where.getStartPosition(); const layoutInfo = this.editor.getLayoutInfo(); const width = this._getWidth(layoutInfo); this.domNode.style.width = `${width}px`; @@ -432,14 +425,23 @@ export abstract class ZoneWidget implements IHorizontalSashLayoutProvider { const model = this.editor.getModel(); if (model) { - // Reveal the line above or below the zone widget, to get the zone widget in the viewport - const revealLineNumber = Math.min(model.getLineCount(), Math.max(1, where.endLineNumber + 1)); - this.revealLine(revealLineNumber); + const revealLine = where.endLineNumber + 1; + if (revealLine <= model.getLineCount()) { + // reveal line below the zone widget + this.revealLine(revealLine, false); + } else { + // reveal last line atop + this.revealLine(model.getLineCount(), true); + } } } - protected revealLine(lineNumber: number) { - this.editor.revealLine(lineNumber, ScrollType.Smooth); + protected revealLine(lineNumber: number, isLastLine: boolean) { + if (isLastLine) { + this.editor.revealLineInCenter(lineNumber, ScrollType.Smooth); + } else { + this.editor.revealLine(lineNumber, ScrollType.Smooth); + } } protected setCssClass(className: string, classToReplace?: string): void { diff --git a/src/vs/editor/test/common/viewModel/prefixSumComputer.test.ts b/src/vs/editor/test/common/viewModel/prefixSumComputer.test.ts index 11cc42efb8d..313c672b101 100644 --- a/src/vs/editor/test/common/viewModel/prefixSumComputer.test.ts +++ b/src/vs/editor/test/common/viewModel/prefixSumComputer.test.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import * as assert from 'assert'; -import { toUint32Array } from 'vs/editor/common/core/uint'; +import { toUint32Array } from 'vs/base/common/uint'; import { PrefixSumComputer, PrefixSumIndexOfResult } from 'vs/editor/common/viewModel/prefixSumComputer'; suite('Editor ViewModel - PrefixSumComputer', () => { diff --git a/src/vs/editor/test/common/viewModel/splitLinesCollection.test.ts b/src/vs/editor/test/common/viewModel/splitLinesCollection.test.ts index d57bcaecded..a8b64c4da7a 100644 --- a/src/vs/editor/test/common/viewModel/splitLinesCollection.test.ts +++ b/src/vs/editor/test/common/viewModel/splitLinesCollection.test.ts @@ -9,7 +9,7 @@ import { IViewLineTokens } from 'vs/editor/common/core/lineTokens'; import { Position } from 'vs/editor/common/core/position'; import { IRange, Range } from 'vs/editor/common/core/range'; import { TokenizationResult2 } from 'vs/editor/common/core/token'; -import { toUint32Array } from 'vs/editor/common/core/uint'; +import { toUint32Array } from 'vs/base/common/uint'; import { EndOfLinePreference } from 'vs/editor/common/model'; import { TextModel } from 'vs/editor/common/model/textModel'; import * as modes from 'vs/editor/common/modes'; diff --git a/src/vs/platform/configuration/common/configurationModels.ts b/src/vs/platform/configuration/common/configurationModels.ts index 452e41724c4..533ce1a7c4d 100644 --- a/src/vs/platform/configuration/common/configurationModels.ts +++ b/src/vs/platform/configuration/common/configurationModels.ts @@ -605,6 +605,7 @@ export class ConfigurationChangeEvent extends AbstractConfigurationChangeEvent i private _changedConfiguration: ConfigurationModel = new ConfigurationModel(), private _changedConfigurationByResource: ResourceMap<ConfigurationModel> = new ResourceMap<ConfigurationModel>()) { super(); + this._source = ConfigurationTarget.DEFAULT; } get changedConfiguration(): IConfigurationModel { diff --git a/src/vs/platform/configuration/common/configurationRegistry.ts b/src/vs/platform/configuration/common/configurationRegistry.ts index 32d66562f55..8a346c09ca4 100644 --- a/src/vs/platform/configuration/common/configurationRegistry.ts +++ b/src/vs/platform/configuration/common/configurationRegistry.ts @@ -173,7 +173,7 @@ class ConfigurationRegistry implements IConfigurationRegistry { this.editorConfigurationSchema = { properties: {}, patternProperties: {}, additionalProperties: false, errorMessage: 'Unknown editor configuration setting', allowTrailingCommas: true, allowComments: true }; this.configurationProperties = {}; this.excludedConfigurationProperties = {}; - this.computeOverridePropertyPattern(); + this.overridePropertyPattern = this.computeOverridePropertyPattern(); contributionRegistry.registerSchema(editorConfigurationSchemaId, this.editorConfigurationSchema); } @@ -413,7 +413,7 @@ class ConfigurationRegistry implements IConfigurationRegistry { delete windowSettings.patternProperties[this.overridePropertyPattern]; delete resourceSettings.patternProperties[this.overridePropertyPattern]; - this.computeOverridePropertyPattern(); + this.overridePropertyPattern = this.computeOverridePropertyPattern(); allSettings.patternProperties[this.overridePropertyPattern] = patternProperties; applicationSettings.patternProperties[this.overridePropertyPattern] = patternProperties; @@ -440,8 +440,8 @@ class ConfigurationRegistry implements IConfigurationRegistry { } } - private computeOverridePropertyPattern(): void { - this.overridePropertyPattern = this.overrideIdentifiers.length ? OVERRIDE_PATTERN_WITH_SUBSTITUTION.replace('${0}', this.overrideIdentifiers.map(identifier => strings.createRegExp(identifier, false).source).join('|')) : OVERRIDE_PROPERTY; + private computeOverridePropertyPattern(): string { + return this.overrideIdentifiers.length ? OVERRIDE_PATTERN_WITH_SUBSTITUTION.replace('${0}', this.overrideIdentifiers.map(identifier => strings.createRegExp(identifier, false).source).join('|')) : OVERRIDE_PROPERTY; } } diff --git a/src/vs/platform/environment/common/environment.ts b/src/vs/platform/environment/common/environment.ts index 99a9753a4df..4a3db2fa2a5 100644 --- a/src/vs/platform/environment/common/environment.ts +++ b/src/vs/platform/environment/common/environment.ts @@ -74,7 +74,13 @@ export interface ParsedArgs { 'force'?: boolean; 'force-user-env'?: boolean; - // node flags + // chromium command line args: https://electronjs.org/docs/all#supported-chrome-command-line-switches + 'no-proxy-server'?: boolean; + 'proxy-server'?: string; + 'proxy-bypass-list'?: string; + 'proxy-pac-url'?: string; + 'inspect'?: string; + 'inspect-brk'?: string; 'js-flags'?: string; 'disable-gpu'?: boolean; 'nolazy'?: boolean; diff --git a/src/vs/platform/environment/node/argv.ts b/src/vs/platform/environment/node/argv.ts index 5b49fd0dd46..3721d14c40e 100644 --- a/src/vs/platform/environment/node/argv.ts +++ b/src/vs/platform/environment/node/argv.ts @@ -111,7 +111,14 @@ export const OPTIONS: OptionDescriptions<Required<ParsedArgs>> = { 'trace-options': { type: 'string' }, 'force-user-env': { type: 'boolean' }, + // chromium flags + 'no-proxy-server': { type: 'boolean' }, + 'proxy-server': { type: 'string' }, + 'proxy-bypass-list': { type: 'string' }, + 'proxy-pac-url': { type: 'string' }, 'js-flags': { type: 'string' }, // chrome js flags + 'inspect': { type: 'string' }, + 'inspect-brk': { type: 'string' }, 'nolazy': { type: 'boolean' }, // node inspect '_urls': { type: 'string[]' }, diff --git a/src/vs/platform/files/node/diskFileSystemProvider.ts b/src/vs/platform/files/node/diskFileSystemProvider.ts index a7d483ffda2..814888252d9 100644 --- a/src/vs/platform/files/node/diskFileSystemProvider.ts +++ b/src/vs/platform/files/node/diskFileSystemProvider.ts @@ -3,14 +3,14 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { mkdir, open, close, read, write, fdatasync } from 'fs'; +import { mkdir, open, close, read, write, fdatasync, Dirent, Stats } from 'fs'; import { promisify } from 'util'; import { IDisposable, Disposable, toDisposable, dispose, combinedDisposable } from 'vs/base/common/lifecycle'; import { IFileSystemProvider, FileSystemProviderCapabilities, IFileChange, IWatchOptions, IStat, FileType, FileDeleteOptions, FileOverwriteOptions, FileWriteOptions, FileOpenOptions, FileSystemProviderErrorCode, createFileSystemProviderError, FileSystemProviderError } from 'vs/platform/files/common/files'; import { URI } from 'vs/base/common/uri'; import { Event, Emitter } from 'vs/base/common/event'; import { isLinux, isWindows } from 'vs/base/common/platform'; -import { statLink, readdir, unlink, move, copy, readFile, truncate, rimraf, RimRafMode, exists } from 'vs/base/node/pfs'; +import { statLink, unlink, move, copy, readFile, truncate, rimraf, RimRafMode, exists, readdirWithFileTypes } from 'vs/base/node/pfs'; import { normalize, basename, dirname } from 'vs/base/common/path'; import { joinPath } from 'vs/base/common/resources'; import { isEqual } from 'vs/base/common/extpath'; @@ -62,15 +62,8 @@ export class DiskFileSystemProvider extends Disposable implements IFileSystemPro try { const { stat, isSymbolicLink } = await statLink(this.toFilePath(resource)); // cannot use fs.stat() here to support links properly - let type: number; - if (isSymbolicLink) { - type = FileType.SymbolicLink | (stat.isDirectory() ? FileType.Directory : FileType.File); - } else { - type = stat.isFile() ? FileType.File : stat.isDirectory() ? FileType.Directory : FileType.Unknown; - } - return { - type, + type: this.toType(stat, isSymbolicLink), ctime: stat.ctime.getTime(), mtime: stat.mtime.getTime(), size: stat.size @@ -82,13 +75,19 @@ export class DiskFileSystemProvider extends Disposable implements IFileSystemPro async readdir(resource: URI): Promise<[string, FileType][]> { try { - const children = await readdir(this.toFilePath(resource)); + const children = await readdirWithFileTypes(this.toFilePath(resource)); const result: [string, FileType][] = []; await Promise.all(children.map(async child => { try { - const stat = await this.stat(joinPath(resource, child)); - result.push([child, stat.type]); + let type: FileType; + if (child.isSymbolicLink()) { + type = (await this.stat(joinPath(resource, child.name))).type; // always resolve target the link points to if any + } else { + type = this.toType(child); + } + + result.push([child.name, type]); } catch (error) { this.logService.trace(error); // ignore errors for individual entries that can arise from permission denied } @@ -100,6 +99,14 @@ export class DiskFileSystemProvider extends Disposable implements IFileSystemPro } } + private toType(entry: Stats | Dirent, isSymbolicLink = entry.isSymbolicLink()): FileType { + if (isSymbolicLink) { + return FileType.SymbolicLink | (entry.isDirectory() ? FileType.Directory : FileType.File); + } + + return entry.isFile() ? FileType.File : entry.isDirectory() ? FileType.Directory : FileType.Unknown; + } + //#endregion //#region File Reading/Writing diff --git a/src/vs/platform/files/node/watcher/unix/chokidarWatcherService.ts b/src/vs/platform/files/node/watcher/unix/chokidarWatcherService.ts index 3fff232b834..c91a6a829c9 100644 --- a/src/vs/platform/files/node/watcher/unix/chokidarWatcherService.ts +++ b/src/vs/platform/files/node/watcher/unix/chokidarWatcherService.ts @@ -19,6 +19,8 @@ import { IWatcherRequest, IWatcherService, IWatcherOptions } from 'vs/platform/f import { Emitter, Event } from 'vs/base/common/event'; import { equals } from 'vs/base/common/arrays'; +process.noAsar = true; // disable ASAR support in watcher process + interface IWatcher { requests: ExtendedWatcherRequest[]; stop(): any; @@ -50,29 +52,30 @@ export class ChokidarWatcherService implements IWatcherService { private readonly _onLogMessage = new Emitter<ILogMessage>(); readonly onLogMessage: Event<ILogMessage> = this._onLogMessage.event; - public watch(options: IWatcherOptions): Event<IDiskFileChange[]> { + watch(options: IWatcherOptions): Event<IDiskFileChange[]> { this._pollingInterval = options.pollingInterval; this._usePolling = options.usePolling; this._watchers = Object.create(null); this._watcherCount = 0; + return this.onWatchEvent; } - public setVerboseLogging(enabled: boolean): Promise<void> { + setVerboseLogging(enabled: boolean): Promise<void> { this._verboseLogging = enabled; return Promise.resolve(); } - public setRoots(requests: IWatcherRequest[]): Promise<void> { + setRoots(requests: IWatcherRequest[]): Promise<void> { const watchers = Object.create(null); const newRequests: string[] = []; const requestsByBasePath = normalizeRoots(requests); // evaluate new & remaining watchers - for (let basePath in requestsByBasePath) { - let watcher = this._watchers[basePath]; + for (const basePath in requestsByBasePath) { + const watcher = this._watchers[basePath]; if (watcher && isEqualRequests(watcher.requests, requestsByBasePath[basePath])) { watchers[basePath] = watcher; delete this._watchers[basePath]; @@ -80,13 +83,15 @@ export class ChokidarWatcherService implements IWatcherService { newRequests.push(basePath); } } + // stop all old watchers - for (let path in this._watchers) { + for (const path in this._watchers) { this._watchers[path].stop(); } + // start all new watchers - for (let basePath of newRequests) { - let requests = requestsByBasePath[basePath]; + for (const basePath of newRequests) { + const requests = requestsByBasePath[basePath]; watchers[basePath] = this._watch(basePath, requests); } @@ -95,7 +100,7 @@ export class ChokidarWatcherService implements IWatcherService { } // for test purposes - public get wacherCount() { + get wacherCount() { return this._watcherCount; } @@ -121,9 +126,10 @@ export class ChokidarWatcherService implements IWatcherService { }; const excludes: string[] = []; - // if there's only one request, use the built-in ignore-filterering + const isSingleFolder = requests.length === 1; if (isSingleFolder) { + // if there's only one request, use the built-in ignore-filterering excludes.push(...requests[0].excludes); } @@ -133,6 +139,9 @@ export class ChokidarWatcherService implements IWatcherService { excludes.push('/proc/**', '/sys/**'); } } + + excludes.push('**/*.asar'); // Ensure we never recurse into ASAR archives + watcherOpts.ignored = excludes; // Chokidar fails when the basePath does not match case-identical to the path on disk @@ -220,7 +229,7 @@ export class ChokidarWatcherService implements IWatcherService { } } - let event = { type: eventType, path }; + const event = { type: eventType, path }; // Logging if (this._verboseLogging) { @@ -284,12 +293,14 @@ export class ChokidarWatcherService implements IWatcherService { return watcher; } - public stop(): Promise<void> { - for (let path in this._watchers) { - let watcher = this._watchers[path]; + stop(): Promise<void> { + for (const path in this._watchers) { + const watcher = this._watchers[path]; watcher.stop(); } + this._watchers = Object.create(null); + return Promise.resolve(); } @@ -307,25 +318,28 @@ export class ChokidarWatcherService implements IWatcherService { } function isIgnored(path: string, requests: ExtendedWatcherRequest[]): boolean { - for (let request of requests) { + for (const request of requests) { if (request.path === path) { return false; } + if (extpath.isEqualOrParent(path, request.path)) { if (!request.parsedPattern) { if (request.excludes && request.excludes.length > 0) { - let pattern = `{${request.excludes.join(',')}}`; + const pattern = `{${request.excludes.join(',')}}`; request.parsedPattern = glob.parse(pattern); } else { request.parsedPattern = () => false; } } + const relPath = path.substr(request.path.length + 1); if (!request.parsedPattern(relPath)) { return false; } } } + return true; } @@ -335,11 +349,12 @@ function isIgnored(path: string, requests: ExtendedWatcherRequest[]): boolean { */ export function normalizeRoots(requests: IWatcherRequest[]): { [basePath: string]: IWatcherRequest[] } { requests = requests.sort((r1, r2) => r1.path.localeCompare(r2.path)); + let prevRequest: IWatcherRequest | null = null; - let result: { [basePath: string]: IWatcherRequest[] } = Object.create(null); - for (let request of requests) { - let basePath = request.path; - let ignored = (request.excludes || []).sort(); + const result: { [basePath: string]: IWatcherRequest[] } = Object.create(null); + for (const request of requests) { + const basePath = request.path; + const ignored = (request.excludes || []).sort(); if (prevRequest && (extpath.isEqualOrParent(basePath, prevRequest.path))) { if (!isEqualIgnore(ignored, prevRequest.excludes)) { result[prevRequest.path].push({ path: basePath, excludes: ignored }); @@ -349,6 +364,7 @@ export function normalizeRoots(requests: IWatcherRequest[]): { [basePath: string result[basePath] = [prevRequest]; } } + return result; } diff --git a/src/vs/platform/windows/electron-main/windowsMainService.ts b/src/vs/platform/windows/electron-main/windowsMainService.ts index 173db4ee066..6b37e696737 100644 --- a/src/vs/platform/windows/electron-main/windowsMainService.ts +++ b/src/vs/platform/windows/electron-main/windowsMainService.ts @@ -1381,6 +1381,15 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic // Window state is from a previous session: only allow fullscreen when we got updated or user wants to restore else { allowFullscreen = this.lifecycleMainService.wasRestarted || (windowConfig && windowConfig.restoreFullscreen); + + if (allowFullscreen && isMacintosh && WindowsMainService.WINDOWS.some(win => win.isFullScreen)) { + // macOS: Electron does not allow to restore multiple windows in + // fullscreen. As such, if we already restored a window in that + // state, we cannot allow more fullscreen windows. See + // https://github.com/microsoft/vscode/issues/41691 and + // https://github.com/electron/electron/issues/13077 + allowFullscreen = false; + } } if (state.mode === WindowMode.Fullscreen && !allowFullscreen) { diff --git a/src/vs/workbench/api/common/extHost.protocol.ts b/src/vs/workbench/api/common/extHost.protocol.ts index ca01c32fdb6..23de861b428 100644 --- a/src/vs/workbench/api/common/extHost.protocol.ts +++ b/src/vs/workbench/api/common/extHost.protocol.ts @@ -1193,7 +1193,7 @@ export interface ExtHostTerminalServiceShape { $acceptTerminalTitleChange(id: number, name: string): void; $acceptTerminalDimensions(id: number, cols: number, rows: number): void; $acceptTerminalMaximumDimensions(id: number, cols: number, rows: number): void; - $spawnExtHostProcess(id: number, shellLaunchConfig: IShellLaunchConfigDto, activeWorkspaceRootUri: UriComponents | undefined, cols: number, rows: number, isWorkspaceShellAllowed: boolean): void; + $spawnExtHostProcess(id: number, shellLaunchConfig: IShellLaunchConfigDto, activeWorkspaceRootUri: UriComponents, cols: number, rows: number, isWorkspaceShellAllowed: boolean): void; $startExtensionTerminal(id: number, initialDimensions: ITerminalDimensionsDto | undefined): void; $acceptProcessInput(id: number, data: string): void; $acceptProcessResize(id: number, cols: number, rows: number): void; diff --git a/src/vs/workbench/api/common/extHostTerminalService.ts b/src/vs/workbench/api/common/extHostTerminalService.ts index c109ec77bf6..368f057d8d8 100644 --- a/src/vs/workbench/api/common/extHostTerminalService.ts +++ b/src/vs/workbench/api/common/extHostTerminalService.ts @@ -299,7 +299,7 @@ export abstract class BaseExtHostTerminalService implements IExtHostTerminalServ public abstract createTerminal(name?: string, shellPath?: string, shellArgs?: string[] | string): vscode.Terminal; public abstract createTerminalFromOptions(options: vscode.TerminalOptions): vscode.Terminal; public abstract getDefaultShell(useAutomationShell: boolean, configProvider: ExtHostConfigProvider): string; - public abstract $spawnExtHostProcess(id: number, shellLaunchConfigDto: IShellLaunchConfigDto, activeWorkspaceRootUriComponents: UriComponents | undefined, cols: number, rows: number, isWorkspaceShellAllowed: boolean): Promise<void>; + public abstract $spawnExtHostProcess(id: number, shellLaunchConfigDto: IShellLaunchConfigDto, activeWorkspaceRootUriComponents: UriComponents, cols: number, rows: number, isWorkspaceShellAllowed: boolean): Promise<void>; public abstract $requestAvailableShells(): Promise<IShellDefinitionDto[]>; public abstract $requestDefaultShellAndArgs(useAutomationShell: boolean): Promise<IShellAndArgsDto>; public abstract $acceptWorkspacePermissionsChanged(isAllowed: boolean): void; @@ -577,7 +577,7 @@ export class WorkerExtHostTerminalService extends BaseExtHostTerminalService { throw new Error('Not implemented'); } - public $spawnExtHostProcess(id: number, shellLaunchConfigDto: IShellLaunchConfigDto, activeWorkspaceRootUriComponents: UriComponents | undefined, cols: number, rows: number, isWorkspaceShellAllowed: boolean): Promise<void> { + public $spawnExtHostProcess(id: number, shellLaunchConfigDto: IShellLaunchConfigDto, activeWorkspaceRootUriComponents: UriComponents, cols: number, rows: number, isWorkspaceShellAllowed: boolean): Promise<void> { throw new Error('Not implemented'); } diff --git a/src/vs/workbench/api/common/extHostTypeConverters.ts b/src/vs/workbench/api/common/extHostTypeConverters.ts index 608b6d90707..24dd0936044 100644 --- a/src/vs/workbench/api/common/extHostTypeConverters.ts +++ b/src/vs/workbench/api/common/extHostTypeConverters.ts @@ -283,7 +283,7 @@ export namespace MarkdownString { } let data: any; try { - data = parse(decodeURIComponent(part)); + data = parse(part); } catch (e) { // ignore } diff --git a/src/vs/workbench/api/node/extHostDebugService.ts b/src/vs/workbench/api/node/extHostDebugService.ts index 4f91793edfc..474c69813d1 100644 --- a/src/vs/workbench/api/node/extHostDebugService.ts +++ b/src/vs/workbench/api/node/extHostDebugService.ts @@ -82,12 +82,12 @@ export class ExtHostDebugService implements IExtHostDebugService, ExtHostDebugSe private _debugAdapters: Map<number, IDebugAdapter>; private _debugAdaptersTrackers: Map<number, vscode.DebugAdapterTracker>; - private _variableResolver: IConfigurationResolverService; + private _variableResolver: IConfigurationResolverService | undefined; private _integratedTerminalInstance?: vscode.Terminal; - private _terminalDisposedListener: IDisposable; + private _terminalDisposedListener: IDisposable | undefined; - private _signService: ISignService; + private _signService: ISignService | undefined; constructor( @@ -1070,10 +1070,8 @@ interface IDapTransport { class DirectDebugAdapter extends AbstractDebugAdapter implements IDapTransport { - readonly onError: Event<Error>; - readonly onExit: Event<number>; - private _sendUp: (msg: DebugProtocol.ProtocolMessage) => void; + private _sendUp!: (msg: DebugProtocol.ProtocolMessage) => void; constructor(implementation: any) { super(); diff --git a/src/vs/workbench/api/node/extHostTerminalService.ts b/src/vs/workbench/api/node/extHostTerminalService.ts index 1928820a110..13831193a59 100644 --- a/src/vs/workbench/api/node/extHostTerminalService.ts +++ b/src/vs/workbench/api/node/extHostTerminalService.ts @@ -123,7 +123,7 @@ export class ExtHostTerminalService extends BaseExtHostTerminalService { this._variableResolver = new ExtHostVariableResolverService(workspaceFolders || [], this._extHostDocumentsAndEditors, configProvider); } - public async $spawnExtHostProcess(id: number, shellLaunchConfigDto: IShellLaunchConfigDto, activeWorkspaceRootUriComponents: UriComponents | undefined, cols: number, rows: number, isWorkspaceShellAllowed: boolean): Promise<void> { + public async $spawnExtHostProcess(id: number, shellLaunchConfigDto: IShellLaunchConfigDto, activeWorkspaceRootUriComponents: UriComponents, cols: number, rows: number, isWorkspaceShellAllowed: boolean): Promise<void> { const shellLaunchConfig: IShellLaunchConfig = { name: shellLaunchConfigDto.name, executable: shellLaunchConfigDto.executable, @@ -155,23 +155,17 @@ export class ExtHostTerminalService extends BaseExtHostTerminalService { } } - let lastActiveWorkspace: IWorkspaceFolder | null = null; - let activeWorkspaceRootUri: URI | undefined; - if (activeWorkspaceRootUriComponents) { - let activeWorkspaceRootUri = URI.revive(activeWorkspaceRootUriComponents); - // Get the environment - const apiLastActiveWorkspace = await this._extHostWorkspace.getWorkspaceFolder(activeWorkspaceRootUri); - if (apiLastActiveWorkspace) { - lastActiveWorkspace = { - uri: apiLastActiveWorkspace.uri, - name: apiLastActiveWorkspace.name, - index: apiLastActiveWorkspace.index, - toResource: () => { - throw new Error('Not implemented'); - } - }; + const activeWorkspaceRootUri = URI.revive(activeWorkspaceRootUriComponents); + // Get the environment + const apiLastActiveWorkspace = await this._extHostWorkspace.getWorkspaceFolder(activeWorkspaceRootUri); + const lastActiveWorkspace = apiLastActiveWorkspace ? { + uri: apiLastActiveWorkspace.uri, + name: apiLastActiveWorkspace.name, + index: apiLastActiveWorkspace.index, + toResource: () => { + throw new Error('Not implemented'); } - } + } as IWorkspaceFolder : null; // Get the initial cwd const terminalConfig = configProvider.getConfiguration('terminal.integrated'); diff --git a/src/vs/workbench/browser/parts/editor/editor.contribution.ts b/src/vs/workbench/browser/parts/editor/editor.contribution.ts index 717579e2883..1329bd6a791 100644 --- a/src/vs/workbench/browser/parts/editor/editor.contribution.ts +++ b/src/vs/workbench/browser/parts/editor/editor.contribution.ts @@ -585,7 +585,7 @@ appendEditorToolItem( appendEditorToolItem( { id: editorCommands.TOGGLE_DIFF_IGNORE_TRIM_WHITESPACE, - title: nls.localize('ignoreTrimWhitespace.label', "Ignore Trim Whitespace"), + title: nls.localize('ignoreTrimWhitespace.label', "Ignore Leading/Trailing Whitespace Differences"), iconDark: URI.parse(registerAndGetAmdImageURL('vs/workbench/browser/parts/editor/media/paragraph-dark.svg')), iconLight: URI.parse(registerAndGetAmdImageURL('vs/workbench/browser/parts/editor/media/paragraph-light.svg')) }, @@ -597,7 +597,7 @@ appendEditorToolItem( appendEditorToolItem( { id: editorCommands.TOGGLE_DIFF_IGNORE_TRIM_WHITESPACE, - title: nls.localize('showTrimWhitespace.label', "Show Trim Whitespace"), + title: nls.localize('showTrimWhitespace.label', "Show Leading/Trailing Whitespace Differences"), iconDark: URI.parse(registerAndGetAmdImageURL('vs/workbench/browser/parts/editor/media/paragraph-disabled-dark.svg')), iconLight: URI.parse(registerAndGetAmdImageURL('vs/workbench/browser/parts/editor/media/paragraph-disabled-light.svg')) }, diff --git a/src/vs/workbench/browser/parts/editor/editorGroupView.ts b/src/vs/workbench/browser/parts/editor/editorGroupView.ts index 3687fb2cba5..83579569c37 100644 --- a/src/vs/workbench/browser/parts/editor/editorGroupView.ts +++ b/src/vs/workbench/browser/parts/editor/editorGroupView.ts @@ -1523,7 +1523,7 @@ export class EditorGroupView extends Themable implements IEditorGroupView { } class EditorOpeningEvent implements IEditorOpeningEvent { - private override: () => Promise<IEditor | undefined> | undefined; + private override: (() => Promise<IEditor | undefined>) | undefined = undefined; constructor( private _group: GroupIdentifier, @@ -1548,7 +1548,7 @@ class EditorOpeningEvent implements IEditorOpeningEvent { this.override = callback; } - isPrevented(): () => Promise<IEditor | undefined> | undefined { + isPrevented(): (() => Promise<IEditor | undefined>) | undefined { return this.override; } } diff --git a/src/vs/workbench/browser/parts/editor/media/tabstitlecontrol.css b/src/vs/workbench/browser/parts/editor/media/tabstitlecontrol.css index 532c3378244..2e5c93ce321 100644 --- a/src/vs/workbench/browser/parts/editor/media/tabstitlecontrol.css +++ b/src/vs/workbench/browser/parts/editor/media/tabstitlecontrol.css @@ -232,6 +232,10 @@ padding-right: 5px; /* we need less room when sizing is shrink */ } +.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.close-button-off.dirty-border-top > .tab-close { + display: none; /* hide dirty state when highlightModifiedTabs is enabled and when running without close button */ +} + .monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.close-button-off.dirty:not(.dirty-border-top) { padding-right: 0; /* remove extra padding when we are running without close button */ } diff --git a/src/vs/workbench/contrib/codeEditor/browser/codeEditor.contribution.ts b/src/vs/workbench/contrib/codeEditor/browser/codeEditor.contribution.ts index 39a4d1afe66..dcc524d15e7 100644 --- a/src/vs/workbench/contrib/codeEditor/browser/codeEditor.contribution.ts +++ b/src/vs/workbench/contrib/codeEditor/browser/codeEditor.contribution.ts @@ -5,6 +5,7 @@ import './menuPreventer'; import './accessibility/accessibility'; +import './diffEditorHelper'; import './inspectKeybindings'; import './largeFileOptimizations'; import './selectionClipboard'; diff --git a/src/vs/workbench/contrib/codeEditor/browser/diffEditorHelper.ts b/src/vs/workbench/contrib/codeEditor/browser/diffEditorHelper.ts new file mode 100644 index 00000000000..eed47f4fad8 --- /dev/null +++ b/src/vs/workbench/contrib/codeEditor/browser/diffEditorHelper.ts @@ -0,0 +1,91 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import * as nls from 'vs/nls'; +import { IDiffEditor } from 'vs/editor/browser/editorBrowser'; +import { registerDiffEditorContribution } from 'vs/editor/browser/editorExtensions'; +import { IEditorContribution } from 'vs/editor/common/editorCommon'; +import { Disposable, IDisposable } from 'vs/base/common/lifecycle'; +import { FloatingClickWidget } from 'vs/workbench/browser/parts/editor/editorWidgets'; +import { IDiffComputationResult } from 'vs/editor/common/services/editorWorkerService'; +import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; +import { IConfigurationService, ConfigurationTarget } from 'vs/platform/configuration/common/configuration'; + +const enum WidgetState { + Hidden, + HintWhitespace +} + +class DiffEditorHelperContribution extends Disposable implements IEditorContribution { + + private _helperWidget: FloatingClickWidget | null; + private _helperWidgetListener: IDisposable | null; + private _state: WidgetState; + + constructor( + private readonly _diffEditor: IDiffEditor, + @IInstantiationService private readonly _instantiationService: IInstantiationService, + @IConfigurationService private readonly _configurationService: IConfigurationService, + ) { + super(); + this._helperWidget = null; + this._helperWidgetListener = null; + this._state = WidgetState.Hidden; + + + this._register(this._diffEditor.onDidUpdateDiff(() => { + this._setState(this._deduceState(this._diffEditor.getDiffComputationResult())); + })); + } + + private _deduceState(diffComputationResult: IDiffComputationResult | null): WidgetState { + if (!diffComputationResult) { + return WidgetState.Hidden; + } + if (this._diffEditor.ignoreTrimWhitespace && diffComputationResult.changes.length === 0 && !diffComputationResult.identical) { + return WidgetState.HintWhitespace; + } + return WidgetState.Hidden; + } + + private _setState(newState: WidgetState) { + if (this._state === newState) { + return; + } + + this._state = newState; + + if (this._helperWidgetListener) { + this._helperWidgetListener.dispose(); + this._helperWidgetListener = null; + } + if (this._helperWidget) { + this._helperWidget.dispose(); + this._helperWidget = null; + } + + if (this._state === WidgetState.HintWhitespace) { + this._helperWidget = this._instantiationService.createInstance(FloatingClickWidget, this._diffEditor.getModifiedEditor(), nls.localize('hintWhitespace', "Show Whitespace Differences"), null); + this._helperWidgetListener = this._helperWidget.onClick(() => this._onDidClickHelperWidget()); + this._helperWidget.render(); + } + } + + private _onDidClickHelperWidget(): void { + if (this._state === WidgetState.HintWhitespace) { + this._configurationService.updateValue('diffEditor.ignoreTrimWhitespace', false, ConfigurationTarget.USER); + } + } + + dispose(): void { + super.dispose(); + } + + getId(): string { + return 'editor.contrib.diffEditorHelper'; + } +} + +registerDiffEditorContribution(DiffEditorHelperContribution); diff --git a/src/vs/workbench/contrib/comments/browser/commentThreadWidget.ts b/src/vs/workbench/contrib/comments/browser/commentThreadWidget.ts index a58e626db11..22807e5c155 100644 --- a/src/vs/workbench/contrib/comments/browser/commentThreadWidget.ts +++ b/src/vs/workbench/contrib/comments/browser/commentThreadWidget.ts @@ -54,21 +54,21 @@ const COMMENT_SCHEME = 'comment'; let INMEM_MODEL_ID = 0; export class ReviewZoneWidget extends ZoneWidget implements ICommentThreadWidget { - private _headElement: HTMLElement; - protected _headingLabel: HTMLElement; - protected _actionbarWidget: ActionBar; - private _bodyElement: HTMLElement; + private _headElement!: HTMLElement; + protected _headingLabel!: HTMLElement; + protected _actionbarWidget!: ActionBar; + private _bodyElement!: HTMLElement; private _parentEditor: ICodeEditor; - private _commentEditor: ICodeEditor; - private _commentsElement: HTMLElement; - private _commentElements: CommentNode[]; - private _commentForm: HTMLElement; - private _reviewThreadReplyButton: HTMLElement; + private _commentEditor!: ICodeEditor; + private _commentsElement!: HTMLElement; + private _commentElements: CommentNode[] = []; + private _commentForm!: HTMLElement; + private _reviewThreadReplyButton!: HTMLElement; private _resizeObserver: any; private readonly _onDidClose = new Emitter<ReviewZoneWidget | undefined>(); private readonly _onDidCreateThread = new Emitter<ReviewZoneWidget>(); private _isExpanded?: boolean; - private _collapseAction: Action; + private _collapseAction!: Action; private _commentGlyph?: CommentGlyphWidget; private _submitActionsDisposables: IDisposable[]; private readonly _globalToDispose = new DisposableStore(); @@ -76,12 +76,12 @@ export class ReviewZoneWidget extends ZoneWidget implements ICommentThreadWidget private _markdownRenderer: MarkdownRenderer; private _styleElement: HTMLStyleElement; private _formActions: HTMLElement | null; - private _error: HTMLElement; + private _error!: HTMLElement; private _contextKeyService: IContextKeyService; private _threadIsEmpty: IContextKey<boolean>; private _commentThreadContextValue: IContextKey<string>; - private _commentEditorIsEmpty: IContextKey<boolean>; - private _commentFormActions: CommentFormActions; + private _commentEditorIsEmpty!: IContextKey<boolean>; + private _commentFormActions!: CommentFormActions; public get owner(): string { return this._owner; @@ -739,7 +739,7 @@ export class ReviewZoneWidget extends ZoneWidget implements ICommentThreadWidget } } - private mouseDownInfo: { lineNumber: number } | null; + private mouseDownInfo: { lineNumber: number } | null = null; private onEditorMouseDown(e: IEditorMouseEvent): void { this.mouseDownInfo = null; diff --git a/src/vs/workbench/contrib/comments/browser/commentsEditorContribution.ts b/src/vs/workbench/contrib/comments/browser/commentsEditorContribution.ts index 87f2dd31cc5..baf4494f753 100644 --- a/src/vs/workbench/contrib/comments/browser/commentsEditorContribution.ts +++ b/src/vs/workbench/contrib/comments/browser/commentsEditorContribution.ts @@ -149,17 +149,17 @@ class CommentingRangeDecorator { export class ReviewController implements IEditorContribution { private readonly globalToDispose = new DisposableStore(); private readonly localToDispose = new DisposableStore(); - private editor: ICodeEditor; + private editor!: ICodeEditor; private _commentWidgets: ReviewZoneWidget[]; private _commentInfos: ICommentInfo[]; - private _commentingRangeDecorator: CommentingRangeDecorator; + private _commentingRangeDecorator!: CommentingRangeDecorator; private mouseDownInfo: { lineNumber: number } | null = null; private _commentingRangeSpaceReserved = false; private _computePromise: CancelablePromise<Array<ICommentInfo | null>> | null; - private _addInProgress: boolean; + private _addInProgress!: boolean; private _emptyThreadsToAddQueue: [number, IEditorMouseEvent | undefined][] = []; - private _computeCommentingRangePromise: CancelablePromise<ICommentInfo[]> | null; - private _computeCommentingRangeScheduler: Delayer<Array<ICommentInfo | null>> | null; + private _computeCommentingRangePromise!: CancelablePromise<ICommentInfo[]> | null; + private _computeCommentingRangeScheduler!: Delayer<Array<ICommentInfo | null>> | null; private _pendingCommentCache: { [key: string]: { [key: string]: string } }; constructor( diff --git a/src/vs/workbench/contrib/debug/browser/breakpointsView.ts b/src/vs/workbench/contrib/debug/browser/breakpointsView.ts index 7f8ffb936c3..624002135be 100644 --- a/src/vs/workbench/contrib/debug/browser/breakpointsView.ts +++ b/src/vs/workbench/contrib/debug/browser/breakpointsView.ts @@ -14,7 +14,7 @@ import { IContextMenuService, IContextViewService } from 'vs/platform/contextvie import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; import { IThemeService } from 'vs/platform/theme/common/themeService'; -import { Constants } from 'vs/editor/common/core/uint'; +import { Constants } from 'vs/base/common/uint'; import { dispose, IDisposable } from 'vs/base/common/lifecycle'; import { Separator } from 'vs/base/browser/ui/actionbar/actionbar'; import { IListVirtualDelegate, IListContextMenuEvent, IListRenderer } from 'vs/base/browser/ui/list/list'; diff --git a/src/vs/workbench/contrib/debug/browser/debugCallStackContribution.ts b/src/vs/workbench/contrib/debug/browser/debugCallStackContribution.ts index 68cf65a7931..d102042652b 100644 --- a/src/vs/workbench/contrib/debug/browser/debugCallStackContribution.ts +++ b/src/vs/workbench/contrib/debug/browser/debugCallStackContribution.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { Constants } from 'vs/editor/common/core/uint'; +import { Constants } from 'vs/base/common/uint'; import { Range } from 'vs/editor/common/core/range'; import { ITextModel, TrackedRangeStickiness, IModelDeltaDecoration, IModelDecorationOptions } from 'vs/editor/common/model'; import { IWorkbenchContribution } from 'vs/workbench/common/contributions'; diff --git a/src/vs/workbench/contrib/debug/browser/debugEditorContribution.ts b/src/vs/workbench/contrib/debug/browser/debugEditorContribution.ts index a395d10adc1..3b7f7be2ce8 100644 --- a/src/vs/workbench/contrib/debug/browser/debugEditorContribution.ts +++ b/src/vs/workbench/contrib/debug/browser/debugEditorContribution.ts @@ -7,7 +7,7 @@ import * as nls from 'vs/nls'; import { RunOnceScheduler } from 'vs/base/common/async'; import * as env from 'vs/base/common/platform'; import { visit } from 'vs/base/common/json'; -import { Constants } from 'vs/editor/common/core/uint'; +import { Constants } from 'vs/base/common/uint'; import { KeyCode } from 'vs/base/common/keyCodes'; import { IKeyboardEvent } from 'vs/base/browser/keyboardEvent'; import { StandardTokenType } from 'vs/editor/common/modes'; diff --git a/src/vs/workbench/contrib/debug/browser/debugSession.ts b/src/vs/workbench/contrib/debug/browser/debugSession.ts index bf8a93ef6de..2b3544ea5a0 100644 --- a/src/vs/workbench/contrib/debug/browser/debugSession.ts +++ b/src/vs/workbench/contrib/debug/browser/debugSession.ts @@ -30,8 +30,6 @@ import { Range } from 'vs/editor/common/core/range'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet'; import { ReplModel } from 'vs/workbench/contrib/debug/common/replModel'; -import { onUnexpectedError } from 'vs/base/common/errors'; -import { INotificationService } from 'vs/platform/notification/common/notification'; import { IOpenerService } from 'vs/platform/opener/common/opener'; import { variableSetEmitter } from 'vs/workbench/contrib/debug/browser/variablesView'; import { CancellationTokenSource, CancellationToken } from 'vs/base/common/cancellation'; @@ -74,7 +72,6 @@ export class DebugSession implements IDebugSession { @IConfigurationService private readonly configurationService: IConfigurationService, @IViewletService private readonly viewletService: IViewletService, @IWorkspaceContextService private readonly workspaceContextService: IWorkspaceContextService, - @INotificationService private readonly notificationService: INotificationService, @IProductService private readonly productService: IProductService, @IExtensionHostDebugService private readonly extensionHostDebugService: IExtensionHostDebugService, @IOpenerService private readonly openerService: IOpenerService @@ -183,110 +180,100 @@ export class DebugSession implements IDebugSession { /** * create and initialize a new debug adapter for this session */ - initialize(dbgr: IDebugger): Promise<void> { + async initialize(dbgr: IDebugger): Promise<void> { if (this.raw) { // if there was already a connection make sure to remove old listeners this.shutdown(); } - return dbgr.getCustomTelemetryService().then(customTelemetryService => { - - return dbgr.createDebugAdapter(this).then(debugAdapter => { - - this.raw = new RawDebugSession(debugAdapter, dbgr, this.telemetryService, customTelemetryService, this.extensionHostDebugService, this.openerService); - - return this.raw.start().then(() => { - - this.registerListeners(); - - return this.raw!.initialize({ - clientID: 'vscode', - clientName: this.productService.nameLong, - adapterID: this.configuration.type, - pathFormat: 'path', - linesStartAt1: true, - columnsStartAt1: true, - supportsVariableType: true, // #8858 - supportsVariablePaging: true, // #9537 - supportsRunInTerminalRequest: true, // #10574 - locale: platform.locale - }).then(() => { - this.initialized = true; - this._onDidChangeState.fire(); - this.model.setExceptionBreakpoints(this.raw!.capabilities.exceptionBreakpointFilters || []); - }); - }); + try { + const customTelemetryService = await dbgr.getCustomTelemetryService(); + const debugAdapter = await dbgr.createDebugAdapter(this); + this.raw = new RawDebugSession(debugAdapter, dbgr, this.telemetryService, customTelemetryService, this.extensionHostDebugService, this.openerService); + + await this.raw.start(); + this.registerListeners(); + await this.raw!.initialize({ + clientID: 'vscode', + clientName: this.productService.nameLong, + adapterID: this.configuration.type, + pathFormat: 'path', + linesStartAt1: true, + columnsStartAt1: true, + supportsVariableType: true, // #8858 + supportsVariablePaging: true, // #9537 + supportsRunInTerminalRequest: true, // #10574 + locale: platform.locale }); - }).then(undefined, err => { + this.initialized = true; this._onDidChangeState.fire(); - return Promise.reject(err); - }); + this.model.setExceptionBreakpoints(this.raw!.capabilities.exceptionBreakpointFilters || []); + } catch (err) { + this.initialized = true; + this._onDidChangeState.fire(); + throw err; + } } /** * launch or attach to the debuggee */ - launchOrAttach(config: IConfig): Promise<void> { - if (this.raw) { + async launchOrAttach(config: IConfig): Promise<void> { + if (!this.raw) { + throw new Error('no debug adapter'); + } - // __sessionID only used for EH debugging (but we add it always for now...) - config.__sessionId = this.getId(); + // __sessionID only used for EH debugging (but we add it always for now...) + config.__sessionId = this.getId(); + await this.raw.launchOrAttach(config); - return this.raw.launchOrAttach(config).then(result => { - return undefined; - }); - } - return Promise.reject(new Error('no debug adapter')); } /** * end the current debug adapter session */ - terminate(restart = false): Promise<void> { - if (this.raw) { - this.cancelAllRequests(); - if (this.raw.capabilities.supportsTerminateRequest && this._configuration.resolved.request === 'launch') { - return this.raw.terminate(restart).then(response => { - return undefined; - }); - } - return this.raw.disconnect(restart).then(response => { - return undefined; - }); + async terminate(restart = false): Promise<void> { + if (!this.raw) { + throw new Error('no debug adapter'); + } + + this.cancelAllRequests(); + if (this.raw.capabilities.supportsTerminateRequest && this._configuration.resolved.request === 'launch') { + await this.raw.terminate(restart); + } else { + await this.raw.disconnect(restart); } - return Promise.reject(new Error('no debug adapter')); } /** * end the current debug adapter session */ - disconnect(restart = false): Promise<void> { - if (this.raw) { - this.cancelAllRequests(); - return this.raw.disconnect(restart).then(response => { - return undefined; - }); + async disconnect(restart = false): Promise<void> { + if (!this.raw) { + throw new Error('no debug adapter'); } - return Promise.reject(new Error('no debug adapter')); + + this.cancelAllRequests(); + await this.raw.disconnect(restart); } /** * restart debug adapter session */ - restart(): Promise<void> { - if (this.raw) { - this.cancelAllRequests(); - return this.raw.restart().then(() => undefined); + async restart(): Promise<void> { + if (!this.raw) { + throw new Error('no debug adapter'); } - return Promise.reject(new Error('no debug adapter')); - } - sendBreakpoints(modelUri: URI, breakpointsToSend: IBreakpoint[], sourceModified: boolean): Promise<void> { + this.cancelAllRequests(); + await this.raw.restart(); + } + async sendBreakpoints(modelUri: URI, breakpointsToSend: IBreakpoint[], sourceModified: boolean): Promise<void> { if (!this.raw) { - return Promise.reject(new Error('no debug adapter')); + throw new Error('no debug adapter'); } if (!this.raw.readyForBreakpoints) { @@ -302,237 +289,252 @@ export class DebugSession implements IDebugSession { rawSource.path = normalizeDriveLetter(rawSource.path); } - return this.raw.setBreakpoints({ + const response = await this.raw.setBreakpoints({ source: rawSource, lines: breakpointsToSend.map(bp => bp.sessionAgnosticData.lineNumber), breakpoints: breakpointsToSend.map(bp => ({ line: bp.sessionAgnosticData.lineNumber, column: bp.sessionAgnosticData.column, condition: bp.condition, hitCondition: bp.hitCondition, logMessage: bp.logMessage })), sourceModified - }).then(response => { + }); + if (response && response.body) { + const data = new Map<string, DebugProtocol.Breakpoint>(); + for (let i = 0; i < breakpointsToSend.length; i++) { + data.set(breakpointsToSend[i].getId(), response.body.breakpoints[i]); + } + + this.model.setBreakpointSessionData(this.getId(), this.capabilities, data); + } + } + + async sendFunctionBreakpoints(fbpts: IFunctionBreakpoint[]): Promise<void> { + if (!this.raw) { + throw new Error('no debug adapter'); + } + + if (this.raw.readyForBreakpoints) { + const response = await this.raw.setFunctionBreakpoints({ breakpoints: fbpts }); if (response && response.body) { const data = new Map<string, DebugProtocol.Breakpoint>(); - for (let i = 0; i < breakpointsToSend.length; i++) { - data.set(breakpointsToSend[i].getId(), response.body.breakpoints[i]); + for (let i = 0; i < fbpts.length; i++) { + data.set(fbpts[i].getId(), response.body.breakpoints[i]); } - this.model.setBreakpointSessionData(this.getId(), this.capabilities, data); } - }); + } } - sendFunctionBreakpoints(fbpts: IFunctionBreakpoint[]): Promise<void> { - if (this.raw) { - if (this.raw.readyForBreakpoints) { - return this.raw.setFunctionBreakpoints({ breakpoints: fbpts }).then(response => { - if (response && response.body) { - const data = new Map<string, DebugProtocol.Breakpoint>(); - for (let i = 0; i < fbpts.length; i++) { - data.set(fbpts[i].getId(), response.body.breakpoints[i]); - } - this.model.setBreakpointSessionData(this.getId(), this.capabilities, data); - } - }); - } - - return Promise.resolve(undefined); + async sendExceptionBreakpoints(exbpts: IExceptionBreakpoint[]): Promise<void> { + if (!this.raw) { + throw new Error('no debug adapter'); } - return Promise.reject(new Error('no debug adapter')); + if (this.raw.readyForBreakpoints) { + await this.raw.setExceptionBreakpoints({ filters: exbpts.map(exb => exb.filter) }); + } } - sendExceptionBreakpoints(exbpts: IExceptionBreakpoint[]): Promise<void> { - if (this.raw) { - if (this.raw.readyForBreakpoints) { - return this.raw.setExceptionBreakpoints({ filters: exbpts.map(exb => exb.filter) }).then(() => undefined); - } - return Promise.resolve(undefined); + async dataBreakpointInfo(name: string, variablesReference?: number): Promise<{ dataId: string | null, description: string, canPersist?: boolean }> { + if (!this.raw) { + throw new Error('no debug adapter'); } - return Promise.reject(new Error('no debug adapter')); + if (!this.raw.readyForBreakpoints) { + throw new Error(nls.localize('sessionNotReadyForBreakpoints', "Session is not ready for breakpoints")); + } + + const response = await this.raw.dataBreakpointInfo({ name, variablesReference }); + return response.body; } - dataBreakpointInfo(name: string, variablesReference?: number): Promise<{ dataId: string | null, description: string, canPersist?: boolean }> { - if (this.raw) { - if (this.raw.readyForBreakpoints) { - return this.raw.dataBreakpointInfo({ name, variablesReference }).then(response => response.body); - } - return Promise.reject(new Error(nls.localize('sessionNotReadyForBreakpoints', "Session is not ready for breakpoints"))); + async sendDataBreakpoints(dataBreakpoints: IDataBreakpoint[]): Promise<void> { + if (!this.raw) { + throw new Error('no debug adapter'); } - return Promise.reject(new Error('no debug adapter')); - } - sendDataBreakpoints(dataBreakpoints: IDataBreakpoint[]): Promise<void> { - if (this.raw) { - if (this.raw.readyForBreakpoints) { - return this.raw.setDataBreakpoints({ breakpoints: dataBreakpoints }).then(response => { - if (response && response.body) { - const data = new Map<string, DebugProtocol.Breakpoint>(); - for (let i = 0; i < dataBreakpoints.length; i++) { - data.set(dataBreakpoints[i].getId(), response.body.breakpoints[i]); - } - this.model.setBreakpointSessionData(this.getId(), this.capabilities, data); - } - }); + if (this.raw.readyForBreakpoints) { + const response = await this.raw.setDataBreakpoints({ breakpoints: dataBreakpoints }); + if (response && response.body) { + const data = new Map<string, DebugProtocol.Breakpoint>(); + for (let i = 0; i < dataBreakpoints.length; i++) { + data.set(dataBreakpoints[i].getId(), response.body.breakpoints[i]); + } + this.model.setBreakpointSessionData(this.getId(), this.capabilities, data); } - return Promise.resolve(undefined); } - return Promise.reject(new Error('no debug adapter')); } async breakpointsLocations(uri: URI, lineNumber: number): Promise<IPosition[]> { - if (this.raw) { - const source = this.getRawSource(uri); - const response = await this.raw.breakpointLocations({ source, line: lineNumber }); - if (!response.body || !response.body.breakpoints) { - return []; - } - - const positions = response.body.breakpoints.map(bp => ({ lineNumber: bp.line, column: bp.column || 1 })); + if (!this.raw) { + throw new Error('no debug adapter'); + } - return distinct(positions, p => `${p.lineNumber}:${p.column}`); + const source = this.getRawSource(uri); + const response = await this.raw.breakpointLocations({ source, line: lineNumber }); + if (!response.body || !response.body.breakpoints) { + return []; } - return Promise.reject(new Error('no debug adapter')); + + const positions = response.body.breakpoints.map(bp => ({ lineNumber: bp.line, column: bp.column || 1 })); + + return distinct(positions, p => `${p.lineNumber}:${p.column}`); } customRequest(request: string, args: any): Promise<DebugProtocol.Response> { - if (this.raw) { - return this.raw.custom(request, args); + if (!this.raw) { + throw new Error('no debug adapter'); } - return Promise.reject(new Error('no debug adapter')); + + return this.raw.custom(request, args); } stackTrace(threadId: number, startFrame: number, levels: number): Promise<DebugProtocol.StackTraceResponse> { - if (this.raw) { - const token = this.getNewCancellationToken(threadId); - return this.raw.stackTrace({ threadId, startFrame, levels }, token); + if (!this.raw) { + throw new Error('no debug adapter'); } - return Promise.reject(new Error('no debug adapter')); + + const token = this.getNewCancellationToken(threadId); + return this.raw.stackTrace({ threadId, startFrame, levels }, token); } - exceptionInfo(threadId: number): Promise<IExceptionInfo | undefined> { - if (this.raw) { - return this.raw.exceptionInfo({ threadId }).then(response => { - if (response) { - return { - id: response.body.exceptionId, - description: response.body.description, - breakMode: response.body.breakMode, - details: response.body.details - }; - } - return undefined; - }); + async exceptionInfo(threadId: number): Promise<IExceptionInfo | undefined> { + if (!this.raw) { + throw new Error('no debug adapter'); } - return Promise.reject(new Error('no debug adapter')); + + const response = await this.raw.exceptionInfo({ threadId }); + if (response) { + return { + id: response.body.exceptionId, + description: response.body.description, + breakMode: response.body.breakMode, + details: response.body.details + }; + } + + return undefined; } scopes(frameId: number, threadId: number): Promise<DebugProtocol.ScopesResponse> { - if (this.raw) { - const token = this.getNewCancellationToken(threadId); - return this.raw.scopes({ frameId }, token); + if (!this.raw) { + throw new Error('no debug adapter'); } - return Promise.reject(new Error('no debug adapter')); + + const token = this.getNewCancellationToken(threadId); + return this.raw.scopes({ frameId }, token); } variables(variablesReference: number, threadId: number | undefined, filter: 'indexed' | 'named' | undefined, start: number | undefined, count: number | undefined): Promise<DebugProtocol.VariablesResponse> { - if (this.raw) { - const token = threadId ? this.getNewCancellationToken(threadId) : undefined; - return this.raw.variables({ variablesReference, filter, start, count }, token); + if (!this.raw) { + throw new Error('no debug adapter'); } - return Promise.reject(new Error('no debug adapter')); + + const token = threadId ? this.getNewCancellationToken(threadId) : undefined; + return this.raw.variables({ variablesReference, filter, start, count }, token); } evaluate(expression: string, frameId: number, context?: string): Promise<DebugProtocol.EvaluateResponse> { - if (this.raw) { - return this.raw.evaluate({ expression, frameId, context }); + if (!this.raw) { + throw new Error('no debug adapter'); } - return Promise.reject(new Error('no debug adapter')); + + return this.raw.evaluate({ expression, frameId, context }); } - restartFrame(frameId: number, threadId: number): Promise<void> { - if (this.raw) { - return this.raw.restartFrame({ frameId }, threadId).then(() => undefined); + async restartFrame(frameId: number, threadId: number): Promise<void> { + if (!this.raw) { + throw new Error('no debug adapter'); } - return Promise.reject(new Error('no debug adapter')); + + await this.raw.restartFrame({ frameId }, threadId); } - next(threadId: number): Promise<void> { - if (this.raw) { - return this.raw.next({ threadId }).then(() => undefined); + async next(threadId: number): Promise<void> { + if (!this.raw) { + throw new Error('no debug adapter'); } - return Promise.reject(new Error('no debug adapter')); + + await this.raw.next({ threadId }); } - stepIn(threadId: number): Promise<void> { - if (this.raw) { - return this.raw.stepIn({ threadId }).then(() => undefined); + async stepIn(threadId: number): Promise<void> { + if (!this.raw) { + throw new Error('no debug adapter'); } - return Promise.reject(new Error('no debug adapter')); + + await this.raw.stepIn({ threadId }); } - stepOut(threadId: number): Promise<void> { - if (this.raw) { - return this.raw.stepOut({ threadId }).then(() => undefined); + async stepOut(threadId: number): Promise<void> { + if (!this.raw) { + throw new Error('no debug adapter'); } - return Promise.reject(new Error('no debug adapter')); + + await this.raw.stepOut({ threadId }); } - stepBack(threadId: number): Promise<void> { - if (this.raw) { - return this.raw.stepBack({ threadId }).then(() => undefined); + async stepBack(threadId: number): Promise<void> { + if (!this.raw) { + throw new Error('no debug adapter'); } - return Promise.reject(new Error('no debug adapter')); + + await this.raw.stepBack({ threadId }); } - continue(threadId: number): Promise<void> { - if (this.raw) { - return this.raw.continue({ threadId }).then(() => undefined); + async continue(threadId: number): Promise<void> { + if (!this.raw) { + throw new Error('no debug adapter'); } - return Promise.reject(new Error('no debug adapter')); + + await this.raw.continue({ threadId }); } - reverseContinue(threadId: number): Promise<void> { - if (this.raw) { - return this.raw.reverseContinue({ threadId }).then(() => undefined); + async reverseContinue(threadId: number): Promise<void> { + if (!this.raw) { + throw new Error('no debug adapter'); } - return Promise.reject(new Error('no debug adapter')); + + await this.raw.reverseContinue({ threadId }); } - pause(threadId: number): Promise<void> { - if (this.raw) { - return this.raw.pause({ threadId }).then(() => undefined); + async pause(threadId: number): Promise<void> { + if (!this.raw) { + throw new Error('no debug adapter'); } - return Promise.reject(new Error('no debug adapter')); + + await this.raw.pause({ threadId }); } - terminateThreads(threadIds?: number[]): Promise<void> { - if (this.raw) { - return this.raw.terminateThreads({ threadIds }).then(() => undefined); + async terminateThreads(threadIds?: number[]): Promise<void> { + if (!this.raw) { + throw new Error('no debug adapter'); } - return Promise.reject(new Error('no debug adapter')); + + await this.raw.terminateThreads({ threadIds }); } setVariable(variablesReference: number, name: string, value: string): Promise<DebugProtocol.SetVariableResponse> { - if (this.raw) { - return this.raw.setVariable({ variablesReference, name, value }); + if (!this.raw) { + throw new Error('no debug adapter'); } - return Promise.reject(new Error('no debug adapter')); + + return this.raw.setVariable({ variablesReference, name, value }); } gotoTargets(source: DebugProtocol.Source, line: number, column?: number): Promise<DebugProtocol.GotoTargetsResponse> { - if (this.raw) { - return this.raw.gotoTargets({ source, line, column }); + if (!this.raw) { + throw new Error('no debug adapter'); } - return Promise.reject(new Error('no debug adapter')); + + return this.raw.gotoTargets({ source, line, column }); } goto(threadId: number, targetId: number): Promise<DebugProtocol.GotoResponse> { - if (this.raw) { - return this.raw.goto({ threadId, targetId }); + if (!this.raw) { + throw new Error('no debug adapter'); } - return Promise.reject(new Error('no debug adapter')); + + return this.raw.goto({ threadId, targetId }); } loadSource(resource: URI): Promise<DebugProtocol.SourceResponse> { - if (!this.raw) { return Promise.reject(new Error('no debug adapter')); } @@ -550,50 +552,48 @@ export class DebugSession implements IDebugSession { return this.raw.source({ sourceReference: rawSource.sourceReference || 0, source: rawSource }); } - getLoadedSources(): Promise<Source[]> { - if (this.raw) { - return this.raw.loadedSources({}).then(response => { - if (response.body && response.body.sources) { - return response.body.sources.map(src => this.getSource(src)); - } else { - return []; - } - }, () => { - return []; - }); + async getLoadedSources(): Promise<Source[]> { + if (!this.raw) { + return Promise.reject(new Error('no debug adapter')); + } + + const response = await this.raw.loadedSources({}); + if (response.body && response.body.sources) { + return response.body.sources.map(src => this.getSource(src)); + } else { + return []; } - return Promise.reject(new Error('no debug adapter')); } - completions(frameId: number | undefined, text: string, position: Position, overwriteBefore: number, token: CancellationToken): Promise<CompletionItem[]> { - if (this.raw) { - return this.raw.completions({ - frameId, - text, - column: position.column, - line: position.lineNumber, - }, token).then(response => { - - const result: CompletionItem[] = []; - if (response && response.body && response.body.targets) { - response.body.targets.forEach(item => { - if (item && item.label) { - result.push({ - label: item.label, - insertText: item.text || item.label, - kind: completionKindFromString(item.type || 'property'), - filterText: (item.start && item.length) ? text.substr(item.start, item.length).concat(item.label) : undefined, - range: Range.fromPositions(position.delta(0, -(item.length || overwriteBefore)), position), - sortText: item.sortText - }); - } + async completions(frameId: number | undefined, text: string, position: Position, overwriteBefore: number, token: CancellationToken): Promise<CompletionItem[]> { + if (!this.raw) { + return Promise.reject(new Error('no debug adapter')); + } + + const response = await this.raw.completions({ + frameId, + text, + column: position.column, + line: position.lineNumber, + }, token); + + const result: CompletionItem[] = []; + if (response && response.body && response.body.targets) { + response.body.targets.forEach(item => { + if (item && item.label) { + result.push({ + label: item.label, + insertText: item.text || item.label, + kind: completionKindFromString(item.type || 'property'), + filterText: (item.start && item.length) ? text.substr(item.start, item.length).concat(item.label) : undefined, + range: Range.fromPositions(position.delta(0, -(item.length || overwriteBefore)), position), + sortText: item.sortText }); } - - return result; }); } - return Promise.reject(new Error('no debug adapter')); + + return result; } //---- threads @@ -678,8 +678,9 @@ export class DebugSession implements IDebugSession { } } - private fetchThreads(stoppedDetails?: IRawStoppedDetails): Promise<void> { - return this.raw ? this.raw.threads().then(response => { + private async fetchThreads(stoppedDetails?: IRawStoppedDetails): Promise<void> { + if (this.raw) { + const response = await this.raw.threads(); if (response && response.body && response.body.threads) { this.model.rawUpdate({ sessionId: this.getId(), @@ -687,7 +688,7 @@ export class DebugSession implements IDebugSession { stoppedDetails }); } - }) : Promise.resolve(undefined); + } } //---- private @@ -697,60 +698,63 @@ export class DebugSession implements IDebugSession { return; } - this.rawListeners.push(this.raw.onDidInitialize(() => { + this.rawListeners.push(this.raw.onDidInitialize(async () => { aria.status(nls.localize('debuggingStarted', "Debugging started.")); - const sendConfigurationDone = () => { + const sendConfigurationDone = async () => { if (this.raw && this.raw.capabilities.supportsConfigurationDoneRequest) { - return this.raw.configurationDone().then(undefined, e => { + try { + await this.raw.configurationDone(); + } catch (e) { // Disconnect the debug session on configuration done error #10596 if (this.raw) { this.raw.disconnect(); } - if (e.command !== 'canceled' && e.message !== 'canceled') { - this.notificationService.error(e); - } - }); + } } return undefined; }; // Send all breakpoints - this.debugService.sendAllBreakpoints(this).then(sendConfigurationDone, sendConfigurationDone) - .then(() => this.fetchThreads()); + try { + await this.debugService.sendAllBreakpoints(this); + } finally { + await sendConfigurationDone(); + } + await this.fetchThreads(); })); - this.rawListeners.push(this.raw.onDidStop(event => { - this.fetchThreads(event.body).then(() => { - const thread = typeof event.body.threadId === 'number' ? this.getThread(event.body.threadId) : undefined; - if (thread) { - // Call fetch call stack twice, the first only return the top stack frame. - // Second retrieves the rest of the call stack. For performance reasons #25605 - const promises = this.model.fetchCallStack(<Thread>thread); - const focus = async () => { - if (!event.body.preserveFocusHint && thread.getCallStack().length) { - await this.debugService.focusStackFrame(undefined, thread); - if (thread.stoppedDetails) { - if (this.configurationService.getValue<IDebugConfiguration>('debug').openDebug === 'openOnDebugBreak') { - this.viewletService.openViewlet(VIEWLET_ID); - } - - if (this.configurationService.getValue<IDebugConfiguration>('debug').focusWindowOnBreak) { - this.hostService.focus(); - } + this.rawListeners.push(this.raw.onDidStop(async event => { + await this.fetchThreads(event.body); + const thread = typeof event.body.threadId === 'number' ? this.getThread(event.body.threadId) : undefined; + if (thread) { + // Call fetch call stack twice, the first only return the top stack frame. + // Second retrieves the rest of the call stack. For performance reasons #25605 + const promises = this.model.fetchCallStack(<Thread>thread); + const focus = async () => { + if (!event.body.preserveFocusHint && thread.getCallStack().length) { + await this.debugService.focusStackFrame(undefined, thread); + if (thread.stoppedDetails) { + if (this.configurationService.getValue<IDebugConfiguration>('debug').openDebug === 'openOnDebugBreak') { + this.viewletService.openViewlet(VIEWLET_ID); } - } - }; - promises.topCallStack.then(focus); - promises.wholeCallStack.then(() => { - if (!this.debugService.getViewModel().focusedStackFrame) { - // The top stack frame can be deemphesized so try to focus again #68616 - focus(); + if (this.configurationService.getValue<IDebugConfiguration>('debug').focusWindowOnBreak) { + this.hostService.focus(); + } } - }); + } + }; + + await promises.topCallStack; + focus(); + await promises.wholeCallStack; + if (!this.debugService.getViewModel().focusedStackFrame) { + // The top stack frame can be deemphesized so try to focus again #68616 + focus(); } - }).then(() => this._onDidChangeState.fire()); + } + this._onDidChangeState.fire(); })); this.rawListeners.push(this.raw.onDidThread(event => { @@ -770,12 +774,12 @@ export class DebugSession implements IDebugSession { } })); - this.rawListeners.push(this.raw.onDidTerminateDebugee(event => { + this.rawListeners.push(this.raw.onDidTerminateDebugee(async event => { aria.status(nls.localize('debuggingStopped', "Debugging stopped.")); if (event.body && event.body.restart) { - this.debugService.restartSession(this, event.body.restart).then(undefined, onUnexpectedError); + await this.debugService.restartSession(this, event.body.restart); } else if (this.raw) { - this.raw.disconnect(); + await this.raw.disconnect(); } })); @@ -796,7 +800,7 @@ export class DebugSession implements IDebugSession { })); let outpuPromises: Promise<void>[] = []; - this.rawListeners.push(this.raw.onDidOutput(event => { + this.rawListeners.push(this.raw.onDidOutput(async event => { if (!event.body || !this.raw) { return; } @@ -822,17 +826,21 @@ export class DebugSession implements IDebugSession { } : undefined; if (event.body.variablesReference) { const container = new ExpressionContainer(this, undefined, event.body.variablesReference, generateUuid()); - outpuPromises.push(container.getChildren().then(children => { - return Promise.all(waitFor).then(() => children.forEach(child => { + outpuPromises.push(container.getChildren().then(async children => { + await Promise.all(waitFor); + children.forEach(child => { // Since we can not display multiple trees in a row, we are displaying these variables one after the other (ignoring their names) (<any>child).name = null; this.appendToRepl(child, outputSeverity, source); - })); + }); })); } else if (typeof event.body.output === 'string') { - Promise.all(waitFor).then(() => this.appendToRepl(event.body.output, outputSeverity, source)); + await Promise.all(waitFor); + this.appendToRepl(event.body.output, outputSeverity, source); } - Promise.all(outpuPromises).then(() => outpuPromises = []); + + await Promise.all(outpuPromises); + outpuPromises = []; })); this.rawListeners.push(this.raw.onDidBreakpoint(event => { diff --git a/src/vs/workbench/contrib/debug/browser/rawDebugSession.ts b/src/vs/workbench/contrib/debug/browser/rawDebugSession.ts index 16da4c39488..7c225850acc 100644 --- a/src/vs/workbench/contrib/debug/browser/rawDebugSession.ts +++ b/src/vs/workbench/contrib/debug/browser/rawDebugSession.ts @@ -228,25 +228,23 @@ export class RawDebugSession implements IDisposable { /** * Starts the underlying debug adapter and tracks the session time for telemetry. */ - start(): Promise<void> { + async start(): Promise<void> { if (!this.debugAdapter) { return Promise.reject(new Error('no debug adapter')); } - return this.debugAdapter.startSession().then(() => { - this.startTime = new Date().getTime(); - }, err => { - return Promise.reject(err); - }); + + await this.debugAdapter.startSession(); + this.startTime = new Date().getTime(); } /** * Send client capabilities to the debug adapter and receive DA capabilities in return. */ - initialize(args: DebugProtocol.InitializeRequestArguments): Promise<DebugProtocol.InitializeResponse> { - return this.send('initialize', args).then((response: DebugProtocol.InitializeResponse) => { - this.mergeCapabilities(response.body); - return response; - }); + async initialize(args: DebugProtocol.InitializeRequestArguments): Promise<DebugProtocol.InitializeResponse> { + const response = await this.send('initialize', args); + this.mergeCapabilities(response.body); + + return response; } /** @@ -258,11 +256,11 @@ export class RawDebugSession implements IDisposable { //---- DAP requests - launchOrAttach(config: IConfig): Promise<DebugProtocol.Response> { - return this.send(config.request, config).then(response => { - this.mergeCapabilities(response.body); - return response; - }); + async launchOrAttach(config: IConfig): Promise<DebugProtocol.Response> { + const response = await this.send(config.request, config); + this.mergeCapabilities(response.body); + + return response; } /** @@ -286,35 +284,32 @@ export class RawDebugSession implements IDisposable { return Promise.reject(new Error('restart not supported')); } - next(args: DebugProtocol.NextArguments): Promise<DebugProtocol.NextResponse> { - return this.send('next', args).then(response => { - this.fireSimulatedContinuedEvent(args.threadId); - return response; - }); + async next(args: DebugProtocol.NextArguments): Promise<DebugProtocol.NextResponse> { + const response = await this.send('next', args); + this.fireSimulatedContinuedEvent(args.threadId); + return response; } - stepIn(args: DebugProtocol.StepInArguments): Promise<DebugProtocol.StepInResponse> { - return this.send('stepIn', args).then(response => { - this.fireSimulatedContinuedEvent(args.threadId); - return response; - }); + async stepIn(args: DebugProtocol.StepInArguments): Promise<DebugProtocol.StepInResponse> { + const response = await this.send('stepIn', args); + this.fireSimulatedContinuedEvent(args.threadId); + return response; } - stepOut(args: DebugProtocol.StepOutArguments): Promise<DebugProtocol.StepOutResponse> { - return this.send('stepOut', args).then(response => { - this.fireSimulatedContinuedEvent(args.threadId); - return response; - }); + async stepOut(args: DebugProtocol.StepOutArguments): Promise<DebugProtocol.StepOutResponse> { + const response = await this.send('stepOut', args); + this.fireSimulatedContinuedEvent(args.threadId); + return response; } - continue(args: DebugProtocol.ContinueArguments): Promise<DebugProtocol.ContinueResponse> { - return this.send<DebugProtocol.ContinueResponse>('continue', args).then(response => { - if (response && response.body && response.body.allThreadsContinued !== undefined) { - this.allThreadsContinued = response.body.allThreadsContinued; - } - this.fireSimulatedContinuedEvent(args.threadId, this.allThreadsContinued); - return response; - }); + async continue(args: DebugProtocol.ContinueArguments): Promise<DebugProtocol.ContinueResponse> { + const response = await this.send<DebugProtocol.ContinueResponse>('continue', args); + if (response && response.body && response.body.allThreadsContinued !== undefined) { + this.allThreadsContinued = response.body.allThreadsContinued; + } + this.fireSimulatedContinuedEvent(args.threadId, this.allThreadsContinued); + + return response; } pause(args: DebugProtocol.PauseArguments): Promise<DebugProtocol.PauseResponse> { @@ -335,12 +330,11 @@ export class RawDebugSession implements IDisposable { return Promise.reject(new Error('setVariable not supported')); } - restartFrame(args: DebugProtocol.RestartFrameArguments, threadId: number): Promise<DebugProtocol.RestartFrameResponse> { + async restartFrame(args: DebugProtocol.RestartFrameArguments, threadId: number): Promise<DebugProtocol.RestartFrameResponse> { if (this.capabilities.supportsRestartFrame) { - return this.send('restartFrame', args).then(response => { - this.fireSimulatedContinuedEvent(threadId); - return response; - }); + const response = await this.send('restartFrame', args); + this.fireSimulatedContinuedEvent(threadId); + return response; } return Promise.reject(new Error('restartFrame not supported')); } @@ -433,26 +427,24 @@ export class RawDebugSession implements IDisposable { return this.send<DebugProtocol.EvaluateResponse>('evaluate', args); } - stepBack(args: DebugProtocol.StepBackArguments): Promise<DebugProtocol.StepBackResponse> { + async stepBack(args: DebugProtocol.StepBackArguments): Promise<DebugProtocol.StepBackResponse> { if (this.capabilities.supportsStepBack) { - return this.send('stepBack', args).then(response => { - if (response.body === undefined) { // TODO@AW why this check? - this.fireSimulatedContinuedEvent(args.threadId); - } - return response; - }); + const response = await this.send('stepBack', args); + if (response.body === undefined) { // TODO@AW why this check? + this.fireSimulatedContinuedEvent(args.threadId); + } + return response; } return Promise.reject(new Error('stepBack not supported')); } - reverseContinue(args: DebugProtocol.ReverseContinueArguments): Promise<DebugProtocol.ReverseContinueResponse> { + async reverseContinue(args: DebugProtocol.ReverseContinueArguments): Promise<DebugProtocol.ReverseContinueResponse> { if (this.capabilities.supportsStepBack) { - return this.send('reverseContinue', args).then(response => { - if (response.body === undefined) { // TODO@AW why this check? - this.fireSimulatedContinuedEvent(args.threadId); - } - return response; - }); + const response = await this.send('reverseContinue', args); + if (response.body === undefined) { // TODO@AW why this check? + this.fireSimulatedContinuedEvent(args.threadId); + } + return response; } return Promise.reject(new Error('reverseContinue not supported')); } @@ -464,13 +456,13 @@ export class RawDebugSession implements IDisposable { return Promise.reject(new Error('gotoTargets is not supported')); } - goto(args: DebugProtocol.GotoArguments): Promise<DebugProtocol.GotoResponse> { + async goto(args: DebugProtocol.GotoArguments): Promise<DebugProtocol.GotoResponse> { if (this.capabilities.supportsGotoTargetsRequest) { - return this.send('goto', args).then(res => { - this.fireSimulatedContinuedEvent(args.threadId); - return res; - }); + const response = await this.send('goto', args); + this.fireSimulatedContinuedEvent(args.threadId); + return response; } + return Promise.reject(new Error('goto is not supported')); } @@ -484,36 +476,32 @@ export class RawDebugSession implements IDisposable { //---- private - private shutdown(error?: Error, restart = false): Promise<any> { + private async shutdown(error?: Error, restart = false): Promise<any> { if (!this.inShutdown) { this.inShutdown = true; if (this.debugAdapter) { - return this.send('disconnect', { restart }, undefined, 500).then(() => { - this.stopAdapter(error); - }, () => { - // ignore error + try { + await this.send('disconnect', { restart }, undefined, 500); + } finally { this.stopAdapter(error); - }); + } + } else { + return this.stopAdapter(error); } - return this.stopAdapter(error); } - return Promise.resolve(undefined); } - private stopAdapter(error?: Error): Promise<any> { - if (this.debugAdapter) { - const da = this.debugAdapter; - this.debugAdapter = null; - return da.stopSession().then(_ => { + private async stopAdapter(error?: Error): Promise<any> { + try { + if (this.debugAdapter) { + const da = this.debugAdapter; + this.debugAdapter = null; + await da.stopSession(); this.debugAdapterStopped = true; - this.fireAdapterExitEvent(error); - }, err => { - this.fireAdapterExitEvent(error); - }); - } else { + } + } finally { this.fireAdapterExitEvent(error); } - return Promise.resolve(undefined); } private fireAdapterExitEvent(error?: Error): void { @@ -557,18 +545,19 @@ export class RawDebugSession implements IDisposable { }); break; case 'runInTerminal': - dbgr.runInTerminal(request.arguments as DebugProtocol.RunInTerminalRequestArguments).then(shellProcessId => { + try { + const shellProcessId = await dbgr.runInTerminal(request.arguments as DebugProtocol.RunInTerminalRequestArguments); const resp = response as DebugProtocol.RunInTerminalResponse; resp.body = {}; if (typeof shellProcessId === 'number') { resp.body.shellProcessId = shellProcessId; } safeSendResponse(resp); - }, err => { + } catch (err) { response.success = false; response.message = err.message; safeSendResponse(response); - }); + } break; default: response.success = false; diff --git a/src/vs/workbench/contrib/debug/browser/watchExpressionsView.ts b/src/vs/workbench/contrib/debug/browser/watchExpressionsView.ts index db51214714d..97197e22f06 100644 --- a/src/vs/workbench/contrib/debug/browser/watchExpressionsView.ts +++ b/src/vs/workbench/contrib/debug/browser/watchExpressionsView.ts @@ -24,7 +24,6 @@ import { IAccessibilityProvider } from 'vs/base/browser/ui/list/listWidget'; import { WorkbenchAsyncDataTree } from 'vs/platform/list/browser/listService'; import { IAsyncDataSource, ITreeMouseEvent, ITreeContextMenuEvent, ITreeDragAndDrop, ITreeDragOverReaction } from 'vs/base/browser/ui/tree/tree'; import { IDragAndDropData } from 'vs/base/browser/dnd'; -import { onUnexpectedError } from 'vs/base/common/errors'; import { ElementsDragAndDropData } from 'vs/base/browser/ui/list/listView'; import { FuzzyScore } from 'vs/base/common/filters'; import { IHighlight } from 'vs/base/browser/ui/highlightedlabel/highlightedLabel'; @@ -71,7 +70,7 @@ export class WatchExpressionsView extends ViewletPanel { dnd: new WatchExpressionsDragAndDrop(this.debugService), }); - this.tree.setInput(this.debugService).then(undefined, onUnexpectedError); + this.tree.setInput(this.debugService); CONTEXT_WATCH_EXPRESSIONS_FOCUSED.bindTo(this.tree.contextKeyService); if (this.toolbar) { diff --git a/src/vs/workbench/contrib/debug/common/debugModel.ts b/src/vs/workbench/contrib/debug/common/debugModel.ts index 489315df4b7..7ec9b9ea1f3 100644 --- a/src/vs/workbench/contrib/debug/common/debugModel.ts +++ b/src/vs/workbench/contrib/debug/common/debugModel.ts @@ -114,13 +114,16 @@ export class ExpressionContainer implements IExpressionContainer { return !!this.reference && this.reference > 0; } - private fetchVariables(start: number | undefined, count: number | undefined, filter: 'indexed' | 'named' | undefined): Promise<Variable[]> { - return this.session!.variables(this.reference || 0, this.threadId, filter, start, count).then(response => { + private async fetchVariables(start: number | undefined, count: number | undefined, filter: 'indexed' | 'named' | undefined): Promise<Variable[]> { + try { + const response = await this.session!.variables(this.reference || 0, this.threadId, filter, start, count); return response && response.body && response.body.variables ? distinct(response.body.variables.filter(v => !!v && isString(v.name)), (v: DebugProtocol.Variable) => v.name).map((v: DebugProtocol.Variable) => new Variable(this.session, this.threadId, this, v.variablesReference, v.name, v.evaluateName, v.value, v.namedVariables, v.indexedVariables, v.presentationHint, v.type)) : []; - }, (e: Error) => [new Variable(this.session, this.threadId, this, 0, e.message, e.message, '', 0, 0, { kind: 'virtual' }, undefined, false)]); + } catch (e) { + return [new Variable(this.session, this.threadId, this, 0, e.message, e.message, '', 0, 0, { kind: 'virtual' }, undefined, false)]; + } } // The adapter explicitly sents the children count of an expression only if there are lots of children which should be chunked. diff --git a/src/vs/workbench/contrib/debug/test/browser/debugANSIHandling.test.ts b/src/vs/workbench/contrib/debug/test/browser/debugANSIHandling.test.ts index db1f057192b..bead472a090 100644 --- a/src/vs/workbench/contrib/debug/test/browser/debugANSIHandling.test.ts +++ b/src/vs/workbench/contrib/debug/test/browser/debugANSIHandling.test.ts @@ -30,7 +30,7 @@ suite('Debug - ANSI Handling', () => { */ setup(() => { model = new DebugModel([], [], [], [], [], <any>{ isDirty: (e: any) => false }); - session = new DebugSession({ resolved: { name, type: 'node', request: 'launch' }, unresolved: undefined }, undefined!, model, undefined, undefined!, undefined!, undefined!, undefined!, undefined!, undefined!, undefined!, undefined!, undefined!, NullOpenerService); + session = new DebugSession({ resolved: { name, type: 'node', request: 'launch' }, unresolved: undefined }, undefined!, model, undefined, undefined!, undefined!, undefined!, undefined!, undefined!, undefined!, undefined!, undefined!, NullOpenerService); const instantiationService: TestInstantiationService = <TestInstantiationService>workbenchInstantiationService(); linkDetector = instantiationService.createInstance(LinkDetector); diff --git a/src/vs/workbench/contrib/debug/test/browser/debugModel.test.ts b/src/vs/workbench/contrib/debug/test/browser/debugModel.test.ts index b738c622cea..9198304bfab 100644 --- a/src/vs/workbench/contrib/debug/test/browser/debugModel.test.ts +++ b/src/vs/workbench/contrib/debug/test/browser/debugModel.test.ts @@ -16,7 +16,7 @@ import { IBreakpointUpdateData, IDebugSessionOptions } from 'vs/workbench/contri import { NullOpenerService } from 'vs/platform/opener/common/opener'; function createMockSession(model: DebugModel, name = 'mockSession', options?: IDebugSessionOptions): DebugSession { - return new DebugSession({ resolved: { name, type: 'node', request: 'launch' }, unresolved: undefined }, undefined!, model, options, undefined!, undefined!, undefined!, undefined!, undefined!, undefined!, undefined!, undefined!, undefined!, NullOpenerService); + return new DebugSession({ resolved: { name, type: 'node', request: 'launch' }, unresolved: undefined }, undefined!, model, options, undefined!, undefined!, undefined!, undefined!, undefined!, undefined!, undefined!, undefined!, NullOpenerService); } suite('Debug - Model', () => { diff --git a/src/vs/workbench/contrib/extensions/browser/extensionTipsService.ts b/src/vs/workbench/contrib/extensions/browser/extensionTipsService.ts index 9f40f30c4ca..2e3e9e600d7 100644 --- a/src/vs/workbench/contrib/extensions/browser/extensionTipsService.ts +++ b/src/vs/workbench/contrib/extensions/browser/extensionTipsService.ts @@ -80,7 +80,7 @@ export class ExtensionTipsService extends Disposable implements IExtensionTipsSe private _allIgnoredRecommendations: string[] = []; private _globallyIgnoredRecommendations: string[] = []; private _workspaceIgnoredRecommendations: string[] = []; - private _extensionsRecommendationsUrl: string; + private _extensionsRecommendationsUrl: string | undefined; public loadWorkspaceConfigPromise: Promise<void>; private proactiveRecommendationsFetched: boolean = false; @@ -113,6 +113,8 @@ export class ExtensionTipsService extends Disposable implements IExtensionTipsSe super(); if (!this.isEnabled()) { + this.sessionSeed = 0; + this.loadWorkspaceConfigPromise = Promise.resolve(); return; } diff --git a/src/vs/workbench/contrib/extensions/test/electron-browser/extensionsTipsService.test.ts b/src/vs/workbench/contrib/extensions/test/electron-browser/extensionsTipsService.test.ts index 6114055f8ec..6a381ae5127 100644 --- a/src/vs/workbench/contrib/extensions/test/electron-browser/extensionsTipsService.test.ts +++ b/src/vs/workbench/contrib/extensions/test/electron-browser/extensionsTipsService.test.ts @@ -305,7 +305,6 @@ suite('ExtensionsTipsService Test', () => { function testNoPromptOrRecommendationsForValidRecommendations(recommendations: string[]) { return setUpFolderWorkspace('myFolder', mockTestData.validRecommendedExtensions).then(() => { testObject = instantiationService.createInstance(ExtensionTipsService); - assert.equal(!testObject.loadWorkspaceConfigPromise, true); assert.ok(!prompted); return testObject.getWorkspaceRecommendations().then(() => { diff --git a/src/vs/workbench/contrib/files/browser/fileActions.ts b/src/vs/workbench/contrib/files/browser/fileActions.ts index 3768bc96d17..e44827d52c1 100644 --- a/src/vs/workbench/contrib/files/browser/fileActions.ts +++ b/src/vs/workbench/contrib/files/browser/fileActions.ts @@ -39,7 +39,7 @@ import { Schemas } from 'vs/base/common/network'; import { IDialogService, IConfirmationResult, getConfirmMessage } from 'vs/platform/dialogs/common/dialogs'; import { INotificationService, Severity } from 'vs/platform/notification/common/notification'; import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; -import { Constants } from 'vs/editor/common/core/uint'; +import { Constants } from 'vs/base/common/uint'; import { CLOSE_EDITORS_AND_GROUP_COMMAND_ID } from 'vs/workbench/browser/parts/editor/editorCommands'; import { coalesce } from 'vs/base/common/arrays'; import { AsyncDataTree } from 'vs/base/browser/ui/tree/asyncDataTree'; diff --git a/src/vs/workbench/contrib/splash/electron-browser/partsSplash.contribution.ts b/src/vs/workbench/contrib/splash/electron-browser/partsSplash.contribution.ts index 69b99fd7c0b..a4f15c50597 100644 --- a/src/vs/workbench/contrib/splash/electron-browser/partsSplash.contribution.ts +++ b/src/vs/workbench/contrib/splash/electron-browser/partsSplash.contribution.ts @@ -60,6 +60,8 @@ class PartsSplash { if (e.affectsConfiguration('window.titleBarStyle')) { this._didChangeTitleBarStyle = true; this._savePartsSplash(); + } else if (e.affectsConfiguration('workbench.colorTheme') || e.affectsConfiguration('workbench.colorCustomizations')) { + this._savePartsSplash(); } }, this, this._disposables); } diff --git a/src/vs/workbench/contrib/terminal/browser/terminal.ts b/src/vs/workbench/contrib/terminal/browser/terminal.ts index c3ede8986ad..fa1c7e01354 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminal.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminal.ts @@ -144,7 +144,7 @@ export interface ITerminalService { preparePathForTerminalAsync(path: string, executable: string | undefined, title: string): Promise<string>; extHostReady(remoteAuthority: string): void; - requestSpawnExtHostProcess(proxy: ITerminalProcessExtHostProxy, shellLaunchConfig: IShellLaunchConfig, activeWorkspaceRootUri: URI | undefined, cols: number, rows: number, isWorkspaceShellAllowed: boolean): void; + requestSpawnExtHostProcess(proxy: ITerminalProcessExtHostProxy, shellLaunchConfig: IShellLaunchConfig, activeWorkspaceRootUri: URI, cols: number, rows: number, isWorkspaceShellAllowed: boolean): void; requestStartExtensionTerminal(proxy: ITerminalProcessExtHostProxy, cols: number, rows: number): void; } diff --git a/src/vs/workbench/contrib/terminal/browser/terminalProcessExtHostProxy.ts b/src/vs/workbench/contrib/terminal/browser/terminalProcessExtHostProxy.ts index 3db8f795da5..345840a6410 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalProcessExtHostProxy.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalProcessExtHostProxy.ts @@ -48,7 +48,7 @@ export class TerminalProcessExtHostProxy extends Disposable implements ITerminal constructor( public terminalId: number, shellLaunchConfig: IShellLaunchConfig, - activeWorkspaceRootUri: URI | undefined, + activeWorkspaceRootUri: URI, cols: number, rows: number, configHelper: ITerminalConfigHelper, diff --git a/src/vs/workbench/contrib/terminal/browser/terminalService.ts b/src/vs/workbench/contrib/terminal/browser/terminalService.ts index 173957233b9..052f5ad2392 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalService.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalService.ts @@ -134,7 +134,7 @@ export class TerminalService implements ITerminalService { return activeInstance ? activeInstance : this.createTerminal(undefined); } - public requestSpawnExtHostProcess(proxy: ITerminalProcessExtHostProxy, shellLaunchConfig: IShellLaunchConfig, activeWorkspaceRootUri: URI | undefined, cols: number, rows: number, isWorkspaceShellAllowed: boolean): void { + public requestSpawnExtHostProcess(proxy: ITerminalProcessExtHostProxy, shellLaunchConfig: IShellLaunchConfig, activeWorkspaceRootUri: URI, cols: number, rows: number, isWorkspaceShellAllowed: boolean): void { this._extensionService.whenInstalledExtensionsRegistered().then(async () => { // Wait for the remoteAuthority to be ready (and listening for events) before firing // the event to spawn the ext host process diff --git a/src/vs/workbench/contrib/terminal/common/terminal.ts b/src/vs/workbench/contrib/terminal/common/terminal.ts index f587dbc700f..17acae717b2 100644 --- a/src/vs/workbench/contrib/terminal/common/terminal.ts +++ b/src/vs/workbench/contrib/terminal/common/terminal.ts @@ -342,7 +342,7 @@ export interface ITerminalProcessExtHostProxy extends IDisposable { export interface ISpawnExtHostProcessRequest { proxy: ITerminalProcessExtHostProxy; shellLaunchConfig: IShellLaunchConfig; - activeWorkspaceRootUri: URI | undefined; + activeWorkspaceRootUri: URI; cols: number; rows: number; isWorkspaceShellAllowed: boolean; diff --git a/src/vs/workbench/contrib/webview/browser/dynamicWebviewEditorOverlay.ts b/src/vs/workbench/contrib/webview/browser/dynamicWebviewEditorOverlay.ts index 31f778e3bfc..cceb1698cf4 100644 --- a/src/vs/workbench/contrib/webview/browser/dynamicWebviewEditorOverlay.ts +++ b/src/vs/workbench/contrib/webview/browser/dynamicWebviewEditorOverlay.ts @@ -8,7 +8,7 @@ import { Emitter, Event } from 'vs/base/common/event'; import { Disposable, DisposableStore, MutableDisposable, toDisposable } from 'vs/base/common/lifecycle'; import { URI } from 'vs/base/common/uri'; import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions'; -import { IWebviewService, Webview, WebviewContentOptions, WebviewEditorOverlay, WebviewElement, WebviewOptions } from 'vs/workbench/contrib/webview/browser/webview'; +import { IWebviewService, Webview, WebviewContentOptions, WebviewEditorOverlay, WebviewElement, WebviewOptions, WebviewExtensionDescription } from 'vs/workbench/contrib/webview/browser/webview'; import { IWorkbenchLayoutService, Parts } from 'vs/workbench/services/layout/browser/layoutService'; import { Dimension } from 'vs/base/browser/dom'; import { assertIsDefined } from 'vs/base/common/types'; @@ -25,10 +25,7 @@ export class DynamicWebviewEditorOverlay extends Disposable implements WebviewEd private _html: string = ''; private _initialScrollProgress: number = 0; private _state: string | undefined = undefined; - private _extension: { - readonly location: URI; - readonly id?: ExtensionIdentifier; - } | undefined; + private _extension: WebviewExtensionDescription | undefined; private _owner: any = undefined; diff --git a/src/vs/workbench/contrib/webview/browser/webview.ts b/src/vs/workbench/contrib/webview/browser/webview.ts index 083550bf21d..0cb185a5b0e 100644 --- a/src/vs/workbench/contrib/webview/browser/webview.ts +++ b/src/vs/workbench/contrib/webview/browser/webview.ts @@ -54,14 +54,16 @@ export interface WebviewContentOptions { readonly enableCommandUris?: boolean; } +export interface WebviewExtensionDescription { + readonly location: URI; + readonly id: ExtensionIdentifier; +} + export interface Webview extends IDisposable { html: string; contentOptions: WebviewContentOptions; - extension: { - readonly location: URI; - readonly id?: ExtensionIdentifier; - } | undefined; + extension: WebviewExtensionDescription | undefined; initialScrollProgress: number; state: string | undefined; diff --git a/src/vs/workbench/contrib/webview/browser/webviewElement.ts b/src/vs/workbench/contrib/webview/browser/webviewElement.ts index a80e6b551c0..e33c746b373 100644 --- a/src/vs/workbench/contrib/webview/browser/webviewElement.ts +++ b/src/vs/workbench/contrib/webview/browser/webviewElement.ts @@ -12,7 +12,7 @@ import { IConfigurationService } from 'vs/platform/configuration/common/configur import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions'; import { IFileService } from 'vs/platform/files/common/files'; import { ITunnelService } from 'vs/platform/remote/common/tunnel'; -import { Webview, WebviewContentOptions, WebviewOptions } from 'vs/workbench/contrib/webview/browser/webview'; +import { Webview, WebviewContentOptions, WebviewOptions, WebviewExtensionDescription } from 'vs/workbench/contrib/webview/browser/webview'; import { areWebviewInputOptionsEqual } from 'vs/workbench/contrib/webview/browser/webviewWorkbenchService'; import { WebviewPortMappingManager } from 'vs/workbench/contrib/webview/common/portMapping'; import { loadLocalResource } from 'vs/workbench/contrib/webview/common/resourceLoader'; @@ -35,10 +35,7 @@ export class IFrameWebview extends Disposable implements Webview { private readonly _portMappingManager: WebviewPortMappingManager; - public extension: { - readonly location: URI; - readonly id?: ExtensionIdentifier; - } | undefined; + public extension: WebviewExtensionDescription | undefined; constructor( private readonly id: string, diff --git a/src/vs/workbench/contrib/webview/browser/webviewWorkbenchService.ts b/src/vs/workbench/contrib/webview/browser/webviewWorkbenchService.ts index c0e1994c206..e5b66c96990 100644 --- a/src/vs/workbench/contrib/webview/browser/webviewWorkbenchService.ts +++ b/src/vs/workbench/contrib/webview/browser/webviewWorkbenchService.ts @@ -15,7 +15,7 @@ import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; import { GroupIdentifier } from 'vs/workbench/common/editor'; -import { IWebviewService, WebviewContentOptions, WebviewEditorOverlay, WebviewOptions } from 'vs/workbench/contrib/webview/browser/webview'; +import { IWebviewService, WebviewContentOptions, WebviewEditorOverlay, WebviewOptions, WebviewExtensionDescription } from 'vs/workbench/contrib/webview/browser/webview'; import { IEditorGroup, IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService'; import { ACTIVE_GROUP_TYPE, IEditorService, SIDE_GROUP_TYPE } from 'vs/workbench/services/editor/common/editorService'; import { WebviewInput } from './webviewEditorInput'; @@ -44,11 +44,6 @@ export function areWebviewInputOptionsEqual(a: WebviewInputOptions, b: WebviewIn && equals(a.portMapping, b.portMapping, (a, b) => a.extensionHostPort === b.extensionHostPort && a.webviewPort === b.webviewPort); } -export interface WebviewExtensionDescription { - readonly location: URI; - readonly id: ExtensionIdentifier; -} - export interface IWebviewWorkbenchService { _serviceBrand: undefined; diff --git a/src/vs/workbench/contrib/webview/common/resourceLoader.ts b/src/vs/workbench/contrib/webview/common/resourceLoader.ts index 4c26dae84a4..c0915591caf 100644 --- a/src/vs/workbench/contrib/webview/common/resourceLoader.ts +++ b/src/vs/workbench/contrib/webview/common/resourceLoader.ts @@ -60,7 +60,7 @@ export async function loadLocalResource( authority: extensionLocation.authority, path: '/vscode-resource', query: JSON.stringify({ - requestResourcePath: requestUri.path + requestResourcePath: normalizedPath.path }) }); return resolveContent(fileService, redirectedUri, getWebviewContentMimeType(requestUri)); diff --git a/src/vs/workbench/contrib/webview/electron-browser/webviewElement.ts b/src/vs/workbench/contrib/webview/electron-browser/webviewElement.ts index 9cd4185fd76..01639181a38 100644 --- a/src/vs/workbench/contrib/webview/electron-browser/webviewElement.ts +++ b/src/vs/workbench/contrib/webview/electron-browser/webviewElement.ts @@ -18,7 +18,7 @@ import { IInstantiationService } from 'vs/platform/instantiation/common/instanti import { ITunnelService } from 'vs/platform/remote/common/tunnel'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { IThemeService } from 'vs/platform/theme/common/themeService'; -import { Webview, WebviewContentOptions, WebviewOptions } from 'vs/workbench/contrib/webview/browser/webview'; +import { Webview, WebviewContentOptions, WebviewOptions, WebviewExtensionDescription } from 'vs/workbench/contrib/webview/browser/webview'; import { WebviewPortMappingManager } from 'vs/workbench/contrib/webview/common/portMapping'; import { WebviewResourceScheme } from 'vs/workbench/contrib/webview/common/resourceLoader'; import { WebviewThemeDataProvider } from 'vs/workbench/contrib/webview/common/themeing'; @@ -247,10 +247,7 @@ export class ElectronWebviewBasedWebview extends Disposable implements Webview, private readonly _onDidFocus = this._register(new Emitter<void>()); public readonly onDidFocus: Event<void> = this._onDidFocus.event; - public extension: { - readonly location: URI; - readonly id?: ExtensionIdentifier; - } | undefined; + public extension: WebviewExtensionDescription | undefined; constructor( options: WebviewOptions, diff --git a/src/vs/workbench/services/environment/browser/environmentService.ts b/src/vs/workbench/services/environment/browser/environmentService.ts index b85732fef57..c63d334ec74 100644 --- a/src/vs/workbench/services/environment/browser/environmentService.ts +++ b/src/vs/workbench/services/environment/browser/environmentService.ts @@ -19,19 +19,19 @@ import product from 'vs/platform/product/common/product'; export class BrowserWindowConfiguration implements IWindowConfiguration { - _: any[]; + _!: any[]; - machineId: string; - windowId: number; - logLevel: LogLevel; + machineId!: string; + windowId!: number; + logLevel!: LogLevel; - mainPid: number; + mainPid!: number; - appRoot: string; - execPath: string; + appRoot!: string; + execPath!: string; isInitialStartup?: boolean; - userEnv: IProcessEnvironment; + userEnv!: IProcessEnvironment; nodeCachedDataDir?: string; backupPath?: string; @@ -54,7 +54,7 @@ export class BrowserWindowConfiguration implements IWindowConfiguration { perfStartTime?: number; perfAppReady?: number; perfWindowLoadTime?: number; - perfEntries: ExportData; + perfEntries!: ExportData; filesToOpenOrCreate?: IPath[]; filesToDiff?: IPath[]; @@ -133,14 +133,14 @@ export class BrowserWorkbenchEnvironmentService implements IWorkbenchEnvironment untitledWorkspacesHome: URI; extensionTestsLocationURI?: URI; args: any; - execPath: string; - cliPath: string; + execPath!: string; + cliPath!: string; appRoot: string; - userHome: string; - userDataPath: string; + userHome!: string; + userDataPath!: string; appNameLong: string; appQuality?: string; - appSettingsHome: URI; + appSettingsHome!: URI; userRoamingDataHome: URI; settingsResource: URI; keybindingsResource: URI; @@ -148,37 +148,37 @@ export class BrowserWorkbenchEnvironmentService implements IWorkbenchEnvironment argvResource: URI; settingsSyncPreviewResource: URI; userDataSyncLogResource: URI; - machineSettingsHome: URI; - machineSettingsResource: URI; - globalStorageHome: string; - workspaceStorageHome: string; + machineSettingsHome!: URI; + machineSettingsResource!: URI; + globalStorageHome!: string; + workspaceStorageHome!: string; backupHome: URI; - backupWorkspacesPath: string; - workspacesHome: string; - isExtensionDevelopment: boolean; - disableExtensions: boolean | string[]; - builtinExtensionsPath: string; + backupWorkspacesPath!: string; + workspacesHome!: string; + isExtensionDevelopment!: boolean; + disableExtensions!: boolean | string[]; + builtinExtensionsPath!: string; extensionsPath?: string; extensionDevelopmentLocationURI?: URI[]; extensionTestsPath?: string; debugExtensionHost: IExtensionHostDebugParams; - debugSearch: IDebugParams; - logExtensionHostCommunication: boolean; - isBuilt: boolean; - wait: boolean; - status: boolean; + debugSearch!: IDebugParams; + logExtensionHostCommunication!: boolean; + isBuilt!: boolean; + wait!: boolean; + status!: boolean; log?: string; logsPath: string; - verbose: boolean; - skipReleaseNotes: boolean; - mainIPCHandle: string; - sharedIPCHandle: string; + verbose!: boolean; + skipReleaseNotes!: boolean; + mainIPCHandle!: string; + sharedIPCHandle!: string; nodeCachedDataDir?: string; - installSourcePath: string; - disableUpdates: boolean; - disableCrashReporter: boolean; + installSourcePath!: string; + disableUpdates!: boolean; + disableCrashReporter!: boolean; driverHandle?: string; - driverVerbose: boolean; + driverVerbose!: boolean; galleryMachineIdResource?: URI; readonly logFile: URI; diff --git a/src/vs/workbench/services/extensions/node/extensionPoints.ts b/src/vs/workbench/services/extensions/node/extensionPoints.ts index 17fdf323c7c..5fecc00ac3d 100644 --- a/src/vs/workbench/services/extensions/node/extensionPoints.ts +++ b/src/vs/workbench/services/extensions/node/extensionPoints.ts @@ -51,7 +51,7 @@ class ExtensionManifestParser extends ExtensionManifestHandler { return pfs.readFile(this._absoluteManifestPath).then((manifestContents) => { const errors: json.ParseError[] = []; const manifest = json.parse(manifestContents.toString(), errors); - if (errors.length === 0) { + if (!!manifest && errors.length === 0) { if (manifest.__metadata) { manifest.uuid = manifest.__metadata.id; } diff --git a/src/vs/workbench/services/preferences/browser/preferencesService.ts b/src/vs/workbench/services/preferences/browser/preferencesService.ts index cbde207476f..db55635c1f9 100644 --- a/src/vs/workbench/services/preferences/browser/preferencesService.ts +++ b/src/vs/workbench/services/preferences/browser/preferencesService.ts @@ -51,11 +51,11 @@ export class PreferencesService extends Disposable implements IPreferencesServic private readonly _onDispose = this._register(new Emitter<void>()); private _defaultUserSettingsUriCounter = 0; - private _defaultUserSettingsContentModel: DefaultSettings; + private _defaultUserSettingsContentModel: DefaultSettings | undefined; private _defaultWorkspaceSettingsUriCounter = 0; - private _defaultWorkspaceSettingsContentModel: DefaultSettings; + private _defaultWorkspaceSettingsContentModel: DefaultSettings | undefined; private _defaultFolderSettingsUriCounter = 0; - private _defaultFolderSettingsContentModel: DefaultSettings; + private _defaultFolderSettingsContentModel: DefaultSettings | undefined; constructor( @IEditorService private readonly editorService: IEditorService, diff --git a/src/vs/workbench/services/preferences/common/keybindingsEditorModel.ts b/src/vs/workbench/services/preferences/common/keybindingsEditorModel.ts index 39a4fca36bc..362555816ad 100644 --- a/src/vs/workbench/services/preferences/common/keybindingsEditorModel.ts +++ b/src/vs/workbench/services/preferences/common/keybindingsEditorModel.ts @@ -80,6 +80,8 @@ export class KeybindingsEditorModel extends EditorModel { @IKeybindingService private readonly keybindingsService: IKeybindingService ) { super(); + this._keybindingItems = []; + this._keybindingItemsSortedByPrecedence = []; this.modifierLabels = { ui: UILabelProvider.modifierLabels[os], aria: AriaLabelProvider.modifierLabels[os], diff --git a/src/vs/workbench/services/preferences/common/preferencesModels.ts b/src/vs/workbench/services/preferences/common/preferencesModels.ts index e0f621a144a..61be4700786 100644 --- a/src/vs/workbench/services/preferences/common/preferencesModels.ts +++ b/src/vs/workbench/services/preferences/common/preferencesModels.ts @@ -1249,7 +1249,7 @@ export function defaultKeybindingsContents(keybindingService: IKeybindingService export class DefaultKeybindingsEditorModel implements IKeybindingsEditorModel<any> { - private _content: string; + private _content: string | undefined; constructor(private _uri: URI, @IKeybindingService private readonly keybindingService: IKeybindingService) { diff --git a/src/vs/workbench/services/themes/browser/workbenchThemeService.ts b/src/vs/workbench/services/themes/browser/workbenchThemeService.ts index 69483fa673e..db39fb64c64 100644 --- a/src/vs/workbench/services/themes/browser/workbenchThemeService.ts +++ b/src/vs/workbench/services/themes/browser/workbenchThemeService.ts @@ -73,15 +73,15 @@ export class WorkbenchThemeService implements IWorkbenchThemeService { private container: HTMLElement; private readonly onColorThemeChange: Emitter<IColorTheme>; private watchedColorThemeLocation: URI | undefined; - private watchedColorThemeDisposable: IDisposable; + private watchedColorThemeDisposable: IDisposable | undefined; private iconThemeStore: FileIconThemeStore; private currentIconTheme: FileIconThemeData; private readonly onFileIconThemeChange: Emitter<IFileIconTheme>; private watchedIconThemeLocation: URI | undefined; - private watchedIconThemeDisposable: IDisposable; + private watchedIconThemeDisposable: IDisposable | undefined; - private themingParticipantChangeListener: IDisposable; + private themingParticipantChangeListener: IDisposable | undefined; private get colorCustomizations(): IColorCustomizations { return this.configurationService.getValue<IColorCustomizations>(CUSTOM_WORKBENCH_COLORS_SETTING) || {}; @@ -107,6 +107,7 @@ export class WorkbenchThemeService implements IWorkbenchThemeService { this.iconThemeStore = new FileIconThemeStore(extensionService); this.onColorThemeChange = new Emitter<IColorTheme>({ leakWarningThreshold: 400 }); + this.currentColorTheme = ColorThemeData.createUnloadedTheme(''); this.currentIconTheme = FileIconThemeData.createUnloadedTheme(''); // In order to avoid paint flashing for tokens, because @@ -391,7 +392,7 @@ export class WorkbenchThemeService implements IWorkbenchThemeService { } private applyTheme(newTheme: ColorThemeData, settingsTarget: ConfigurationTarget | undefined | 'auto', silent = false): Promise<IColorTheme | null> { - if (this.currentColorTheme) { + if (this.currentColorTheme.id) { removeClasses(this.container, this.currentColorTheme.id); } else { removeClasses(this.container, VS_DARK_THEME, VS_LIGHT_THEME, VS_HC_THEME); diff --git a/src/vs/workbench/test/electron-browser/api/extHostTypeConverter.test.ts b/src/vs/workbench/test/electron-browser/api/extHostTypeConverter.test.ts index 89a32a67959..aac33827faa 100644 --- a/src/vs/workbench/test/electron-browser/api/extHostTypeConverter.test.ts +++ b/src/vs/workbench/test/electron-browser/api/extHostTypeConverter.test.ts @@ -7,9 +7,10 @@ import * as assert from 'assert'; import { MarkdownString, LogLevel } from 'vs/workbench/api/common/extHostTypeConverters'; import { isEmptyObject } from 'vs/base/common/types'; -import { size } from 'vs/base/common/collections'; +import { size, forEach } from 'vs/base/common/collections'; import * as types from 'vs/workbench/api/common/extHostTypes'; import { LogLevel as _MainLogLevel } from 'vs/platform/log/common/log'; +import { URI } from 'vs/base/common/uri'; suite('ExtHostTypeConverter', function () { @@ -59,6 +60,20 @@ suite('ExtHostTypeConverter', function () { assert.ok(!!data.uris!['file:///somepath/here2']); }); + test('NPM script explorer running a script from the hover does not work #65561', function () { + + let data = MarkdownString.from('*hello* [click](command:npm.runScriptFromHover?%7B%22documentUri%22%3A%7B%22%24mid%22%3A1%2C%22external%22%3A%22file%3A%2F%2F%2Fc%253A%2Ffoo%2Fbaz.ex%22%2C%22path%22%3A%22%2Fc%3A%2Ffoo%2Fbaz.ex%22%2C%22scheme%22%3A%22file%22%7D%2C%22script%22%3A%22dev%22%7D)'); + // assert that both uri get extracted but that the latter is only decoded once... + assert.equal(size(data.uris!), 2); + forEach(data.uris!, entry => { + if (entry.value.scheme === 'file') { + assert.ok(URI.revive(entry.value).toString().indexOf('file:///c%3A') === 0); + } else { + assert.equal(entry.value.scheme, 'command'); + } + }); + }); + test('LogLevel', () => { assert.equal(LogLevel.from(types.LogLevel.Error), _MainLogLevel.Error); assert.equal(LogLevel.from(types.LogLevel.Info), _MainLogLevel.Info); diff --git a/yarn.lock b/yarn.lock index 8b48f5f6231..a0cb9e0f4e4 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3515,12 +3515,7 @@ glogg@^1.0.0: dependencies: sparkles "^1.0.0" -graceful-fs@4.2.2: - version "4.2.2" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.2.tgz#6f0952605d0140c1cfdb138ed005775b92d67b02" - integrity sha512-IItsdsea19BoLC7ELy13q1iJFNmd7ofZH5+X/pJr90/nRoPEX0DJo1dHDbgtYWOhJhcCgMDTOw84RZ72q6lB+Q== - -graceful-fs@^4.0.0, graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.3, graceful-fs@^4.1.6, graceful-fs@^4.1.9: +graceful-fs@4.1.11, graceful-fs@^4.0.0, graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.3, graceful-fs@^4.1.6, graceful-fs@^4.1.9: version "4.1.11" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658" integrity sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg= |