From 3e492a3a5cb9e21d8c25363c5b3152813e393f68 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Wed, 1 Jul 2020 10:24:07 +0200 Subject: [PATCH 01/93] fixes #99447 --- extensions/github/src/publish.ts | 58 +++++++++++++++++--------------- 1 file changed, 30 insertions(+), 28 deletions(-) diff --git a/extensions/github/src/publish.ts b/extensions/github/src/publish.ts index 6926c421f9ab2..cfb318840dad1 100644 --- a/extensions/github/src/publish.ts +++ b/extensions/github/src/publish.ts @@ -97,37 +97,39 @@ export async function publishRepository(gitAPI: GitAPI, repository?: Repository) return; } - quickpick = vscode.window.createQuickPick(); - quickpick.placeholder = localize('ignore', "Select which files should be included in the repository."); - quickpick.canSelectMany = true; - quickpick.show(); - - try { - quickpick.busy = true; - - const repositoryPath = folder.uri.fsPath; - const currentPath = path.join(repositoryPath); - const children = await fs.readdir(currentPath); - quickpick.items = children.map(name => ({ label: name })); - quickpick.selectedItems = quickpick.items; - quickpick.busy = false; + if (!repository) { + quickpick = vscode.window.createQuickPick(); + quickpick.placeholder = localize('ignore', "Select which files should be included in the repository."); + quickpick.canSelectMany = true; + quickpick.show(); + + try { + quickpick.busy = true; + + const repositoryPath = folder.uri.fsPath; + const currentPath = path.join(repositoryPath); + const children = await fs.readdir(currentPath); + quickpick.items = children.map(name => ({ label: name })); + quickpick.selectedItems = quickpick.items; + quickpick.busy = false; + + const result = await Promise.race([ + new Promise(c => quickpick.onDidAccept(() => c(quickpick.selectedItems))), + new Promise(c => quickpick.onDidHide(() => c(undefined))) + ]); + + if (!result) { + return; + } - const result = await Promise.race([ - new Promise(c => quickpick.onDidAccept(() => c(quickpick.selectedItems))), - new Promise(c => quickpick.onDidHide(() => c(undefined))) - ]); + const ignored = new Set(children); + result.forEach(c => ignored.delete(c.label)); - if (!result) { - return; + const raw = [...ignored].map(i => `/${i}`).join('\n'); + await fs.writeFile(path.join(repositoryPath, '.gitignore'), raw, 'utf8'); + } finally { + quickpick.dispose(); } - - const ignored = new Set(children); - result.forEach(c => ignored.delete(c.label)); - - const raw = [...ignored].map(i => `/${i}`).join('\n'); - await fs.writeFile(path.join(repositoryPath, '.gitignore'), raw, 'utf8'); - } finally { - quickpick.dispose(); } const githubRepository = await vscode.window.withProgress({ location: vscode.ProgressLocation.Notification, cancellable: false, title: 'Publish to GitHub' }, async progress => { From ffda3a18cc91411bd11396b62396f7ccc5d04388 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Wed, 1 Jul 2020 10:51:55 +0200 Subject: [PATCH 02/93] fixes #100183 --- extensions/git/src/api/extension.ts | 13 ++++++--- extensions/git/src/util.ts | 12 --------- extensions/github/src/commands.ts | 7 ++--- extensions/github/src/extension.ts | 42 ++++++++++++++++++++--------- extensions/github/src/util.ts | 24 +++++++++++++++++ 5 files changed, 67 insertions(+), 31 deletions(-) create mode 100644 extensions/github/src/util.ts diff --git a/extensions/git/src/api/extension.ts b/extensions/git/src/api/extension.ts index 8d7dc611e6230..f7598fe2f8c9b 100644 --- a/extensions/git/src/api/extension.ts +++ b/extensions/git/src/api/extension.ts @@ -7,7 +7,6 @@ import { Model } from '../model'; import { GitExtension, Repository, API } from './git'; import { ApiRepository, ApiImpl } from './api1'; import { Event, EventEmitter } from 'vscode'; -import { latchEvent } from '../util'; export function deprecated(_target: any, key: string, descriptor: any): void { if (typeof descriptor.value !== 'function') { @@ -26,14 +25,20 @@ export class GitExtensionImpl implements GitExtension { enabled: boolean = false; private _onDidChangeEnablement = new EventEmitter(); - readonly onDidChangeEnablement: Event = latchEvent(this._onDidChangeEnablement.event); + readonly onDidChangeEnablement: Event = this._onDidChangeEnablement.event; private _model: Model | undefined = undefined; set model(model: Model | undefined) { this._model = model; - this.enabled = !!model; + const enabled = !!model; + + if (this.enabled === enabled) { + return; + } + + this.enabled = enabled; this._onDidChangeEnablement.fire(this.enabled); } @@ -73,4 +78,4 @@ export class GitExtensionImpl implements GitExtension { return new ApiImpl(this._model); } -} \ No newline at end of file +} diff --git a/extensions/git/src/util.ts b/extensions/git/src/util.ts index e2ac91ebb1953..fb3519e2b5a94 100644 --- a/extensions/git/src/util.ts +++ b/extensions/git/src/util.ts @@ -44,18 +44,6 @@ export function filterEvent(event: Event, filter: (e: T) => boolean): Even return (listener: (e: T) => any, thisArgs?: any, disposables?: Disposable[]) => event(e => filter(e) && listener.call(thisArgs, e), null, disposables); } -export function latchEvent(event: Event): Event { - let firstCall = true; - let cache: T; - - return filterEvent(event, value => { - let shouldEmit = firstCall || value !== cache; - firstCall = false; - cache = value; - return shouldEmit; - }); -} - export function anyEvent(...events: Event[]): Event { return (listener: (e: T) => any, thisArgs?: any, disposables?: Disposable[]) => { const result = combinedDisposable(events.map(event => event(i => listener.call(thisArgs, i)))); diff --git a/extensions/github/src/commands.ts b/extensions/github/src/commands.ts index a3f0903615f13..dad2982533c1c 100644 --- a/extensions/github/src/commands.ts +++ b/extensions/github/src/commands.ts @@ -6,9 +6,10 @@ import * as vscode from 'vscode'; import { API as GitAPI } from './typings/git'; import { publishRepository } from './publish'; +import { combinedDisposable } from './util'; -export function registerCommands(gitAPI: GitAPI): vscode.Disposable[] { - const disposables = []; +export function registerCommands(gitAPI: GitAPI): vscode.Disposable { + const disposables: vscode.Disposable[] = []; disposables.push(vscode.commands.registerCommand('github.publish', async () => { try { @@ -18,5 +19,5 @@ export function registerCommands(gitAPI: GitAPI): vscode.Disposable[] { } })); - return disposables; + return combinedDisposable(disposables); } diff --git a/extensions/github/src/extension.ts b/extensions/github/src/extension.ts index 51bb15e01fcaf..1d562a98c1f6d 100644 --- a/extensions/github/src/extension.ts +++ b/extensions/github/src/extension.ts @@ -3,23 +3,41 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import * as vscode from 'vscode'; +import { Disposable, ExtensionContext, extensions } from 'vscode'; import { GithubRemoteSourceProvider } from './remoteSourceProvider'; import { GitExtension } from './typings/git'; import { registerCommands } from './commands'; import { GithubCredentialProviderManager } from './credentialProvider'; +import { dispose, combinedDisposable } from './util'; -export async function activate(context: vscode.ExtensionContext) { - const gitExtension = vscode.extensions.getExtension('vscode.git')!.exports; +export function activate(context: ExtensionContext): void { + const disposables = new Set(); + context.subscriptions.push(combinedDisposable(disposables)); - try { - const gitAPI = gitExtension.getAPI(1); + const init = () => { + try { + const gitAPI = gitExtension.getAPI(1); - context.subscriptions.push(...registerCommands(gitAPI)); - context.subscriptions.push(gitAPI.registerRemoteSourceProvider(new GithubRemoteSourceProvider(gitAPI))); - context.subscriptions.push(new GithubCredentialProviderManager(gitAPI)); - } catch (err) { - console.error('Could not initialize GitHub extension'); - console.warn(err); - } + disposables.add(registerCommands(gitAPI)); + disposables.add(gitAPI.registerRemoteSourceProvider(new GithubRemoteSourceProvider(gitAPI))); + disposables.add(new GithubCredentialProviderManager(gitAPI)); + } catch (err) { + console.error('Could not initialize GitHub extension'); + console.warn(err); + } + }; + + const onDidChangeGitExtensionEnablement = (enabled: boolean) => { + if (!enabled) { + dispose(disposables); + disposables.clear(); + } else { + init(); + } + }; + + + const gitExtension = extensions.getExtension('vscode.git')!.exports; + context.subscriptions.push(gitExtension.onDidChangeEnablement(onDidChangeGitExtensionEnablement)); + onDidChangeGitExtensionEnablement(gitExtension.enabled); } diff --git a/extensions/github/src/util.ts b/extensions/github/src/util.ts new file mode 100644 index 0000000000000..60badd28c84b1 --- /dev/null +++ b/extensions/github/src/util.ts @@ -0,0 +1,24 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import * as vscode from 'vscode'; + +export function dispose(arg: vscode.Disposable | Iterable): void { + if (arg instanceof vscode.Disposable) { + arg.dispose(); + } else { + for (const disposable of arg) { + disposable.dispose(); + } + } +} + +export function combinedDisposable(disposables: Iterable): vscode.Disposable { + return { + dispose() { + dispose(disposables); + } + }; +} From 53e793d7fc3907c3175c0abdbcde7c3c23b2b310 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Wed, 1 Jul 2020 10:58:57 +0200 Subject: [PATCH 03/93] use workspace fs --- extensions/github/src/publish.ts | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/extensions/github/src/publish.ts b/extensions/github/src/publish.ts index cfb318840dad1..b8fd49c32a0db 100644 --- a/extensions/github/src/publish.ts +++ b/extensions/github/src/publish.ts @@ -5,10 +5,9 @@ import * as vscode from 'vscode'; import * as nls from 'vscode-nls'; -import * as path from 'path'; -import { promises as fs } from 'fs'; import { API as GitAPI, Repository } from './typings/git'; import { getOctokit } from './auth'; +import { TextEncoder } from 'util'; const localize = nls.loadMessageBundle(); @@ -106,9 +105,7 @@ export async function publishRepository(gitAPI: GitAPI, repository?: Repository) try { quickpick.busy = true; - const repositoryPath = folder.uri.fsPath; - const currentPath = path.join(repositoryPath); - const children = await fs.readdir(currentPath); + const children = (await vscode.workspace.fs.readDirectory(folder.uri)).map(([name]) => name); quickpick.items = children.map(name => ({ label: name })); quickpick.selectedItems = quickpick.items; quickpick.busy = false; @@ -126,7 +123,8 @@ export async function publishRepository(gitAPI: GitAPI, repository?: Repository) result.forEach(c => ignored.delete(c.label)); const raw = [...ignored].map(i => `/${i}`).join('\n'); - await fs.writeFile(path.join(repositoryPath, '.gitignore'), raw, 'utf8'); + const encoder = new TextEncoder(); + await vscode.workspace.fs.writeFile(vscode.Uri.joinPath(folder.uri, '.gitignore'), encoder.encode(raw)); } finally { quickpick.dispose(); } From 91dd76a7f803f2c93ee18094c06645afa1efe31f Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Wed, 1 Jul 2020 11:00:43 +0200 Subject: [PATCH 04/93] high contrast theme: add semanticTokenColors for cpp. For #97177 --- extensions/theme-defaults/themes/hc_black.json | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/extensions/theme-defaults/themes/hc_black.json b/extensions/theme-defaults/themes/hc_black.json index 73309c34b4430..436dfa52912a9 100644 --- a/extensions/theme-defaults/themes/hc_black.json +++ b/extensions/theme-defaults/themes/hc_black.json @@ -122,5 +122,11 @@ "foreground": "#CBEDCB", } } - ] + ], + "semanticTokenColors": { + "newOperator": "#FFFFFF", + "stringLiteral": "#ce9178", + "customLiteral": "#DCDCAA", + "numberLiteral": "#b5cea8", + } } From d3eab32eca1569e4bde78890316aa835435c8523 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Wed, 1 Jul 2020 11:01:59 +0200 Subject: [PATCH 05/93] fixes #100479 --- extensions/github/src/publish.ts | 59 +++++++++++++++++++------------- 1 file changed, 36 insertions(+), 23 deletions(-) diff --git a/extensions/github/src/publish.ts b/extensions/github/src/publish.ts index b8fd49c32a0db..b9a9ee1f8011d 100644 --- a/extensions/github/src/publish.ts +++ b/extensions/github/src/publish.ts @@ -97,39 +97,52 @@ export async function publishRepository(gitAPI: GitAPI, repository?: Repository) } if (!repository) { - quickpick = vscode.window.createQuickPick(); - quickpick.placeholder = localize('ignore', "Select which files should be included in the repository."); - quickpick.canSelectMany = true; - quickpick.show(); + const gitignore = vscode.Uri.joinPath(folder.uri, '.gitignore'); + let shouldGenerateGitignore = false; try { - quickpick.busy = true; + await vscode.workspace.fs.stat(gitignore); + } catch (err) { + shouldGenerateGitignore = true; + } - const children = (await vscode.workspace.fs.readDirectory(folder.uri)).map(([name]) => name); - quickpick.items = children.map(name => ({ label: name })); - quickpick.selectedItems = quickpick.items; - quickpick.busy = false; + if (shouldGenerateGitignore) { + quickpick = vscode.window.createQuickPick(); + quickpick.placeholder = localize('ignore', "Select which files should be included in the repository."); + quickpick.canSelectMany = true; + quickpick.show(); - const result = await Promise.race([ - new Promise(c => quickpick.onDidAccept(() => c(quickpick.selectedItems))), - new Promise(c => quickpick.onDidHide(() => c(undefined))) - ]); + try { + quickpick.busy = true; - if (!result) { - return; - } + const children = (await vscode.workspace.fs.readDirectory(folder.uri)).map(([name]) => name); + quickpick.items = children.map(name => ({ label: name })); + quickpick.selectedItems = quickpick.items; + quickpick.busy = false; - const ignored = new Set(children); - result.forEach(c => ignored.delete(c.label)); + const result = await Promise.race([ + new Promise(c => quickpick.onDidAccept(() => c(quickpick.selectedItems))), + new Promise(c => quickpick.onDidHide(() => c(undefined))) + ]); - const raw = [...ignored].map(i => `/${i}`).join('\n'); - const encoder = new TextEncoder(); - await vscode.workspace.fs.writeFile(vscode.Uri.joinPath(folder.uri, '.gitignore'), encoder.encode(raw)); - } finally { - quickpick.dispose(); + if (!result) { + return; + } + + const ignored = new Set(children); + result.forEach(c => ignored.delete(c.label)); + + const raw = [...ignored].map(i => `/${i}`).join('\n'); + const encoder = new TextEncoder(); + await vscode.workspace.fs.writeFile(gitignore, encoder.encode(raw)); + } finally { + quickpick.dispose(); + } } } + return; + const githubRepository = await vscode.window.withProgress({ location: vscode.ProgressLocation.Notification, cancellable: false, title: 'Publish to GitHub' }, async progress => { progress.report({ message: 'Publishing to GitHub private repository', increment: 25 }); From 2aef194841e1d6a51deb65a88c9f4410f32d2f06 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Wed, 1 Jul 2020 11:07:06 +0200 Subject: [PATCH 06/93] fixes #101409 --- extensions/github/src/publish.ts | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/extensions/github/src/publish.ts b/extensions/github/src/publish.ts index b9a9ee1f8011d..6d58a51ee9b06 100644 --- a/extensions/github/src/publish.ts +++ b/extensions/github/src/publish.ts @@ -8,6 +8,7 @@ import * as nls from 'vscode-nls'; import { API as GitAPI, Repository } from './typings/git'; import { getOctokit } from './auth'; import { TextEncoder } from 'util'; +import { basename } from 'path'; const localize = nls.loadMessageBundle(); @@ -27,10 +28,12 @@ export async function publishRepository(gitAPI: GitAPI, repository?: Repository) return; } - let folder: vscode.WorkspaceFolder; + let folder: vscode.Uri; - if (vscode.workspace.workspaceFolders.length === 1) { - folder = vscode.workspace.workspaceFolders[0]; + if (repository) { + folder = repository.rootUri; + } else if (vscode.workspace.workspaceFolders.length === 1) { + folder = vscode.workspace.workspaceFolders[0].uri; } else { const picks = vscode.workspace.workspaceFolders.map(folder => ({ label: folder.name, folder })); const placeHolder = localize('pick folder', "Pick a folder to publish to GitHub"); @@ -40,14 +43,14 @@ export async function publishRepository(gitAPI: GitAPI, repository?: Repository) return; } - folder = pick.folder; + folder = pick.folder.uri; } let quickpick = vscode.window.createQuickPick(); quickpick.ignoreFocusOut = true; quickpick.placeholder = 'Repository Name'; - quickpick.value = folder.name; + quickpick.value = basename(folder.fsPath); quickpick.show(); quickpick.busy = true; @@ -97,7 +100,7 @@ export async function publishRepository(gitAPI: GitAPI, repository?: Repository) } if (!repository) { - const gitignore = vscode.Uri.joinPath(folder.uri, '.gitignore'); + const gitignore = vscode.Uri.joinPath(folder, '.gitignore'); let shouldGenerateGitignore = false; try { @@ -115,7 +118,7 @@ export async function publishRepository(gitAPI: GitAPI, repository?: Repository) try { quickpick.busy = true; - const children = (await vscode.workspace.fs.readDirectory(folder.uri)).map(([name]) => name); + const children = (await vscode.workspace.fs.readDirectory(folder)).map(([name]) => name); quickpick.items = children.map(name => ({ label: name })); quickpick.selectedItems = quickpick.items; quickpick.busy = false; @@ -156,7 +159,7 @@ export async function publishRepository(gitAPI: GitAPI, repository?: Repository) progress.report({ message: 'Creating first commit', increment: 25 }); if (!repository) { - repository = await gitAPI.init(folder.uri) || undefined; + repository = await gitAPI.init(folder) || undefined; if (!repository) { return; From 4b4e0e0f3f828eb0ea644f4ba25dfe6b4782e7cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Wed, 1 Jul 2020 11:09:58 +0200 Subject: [PATCH 07/93] rogue `return` --- extensions/github/src/publish.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/extensions/github/src/publish.ts b/extensions/github/src/publish.ts index 6d58a51ee9b06..589bd0d3d3c38 100644 --- a/extensions/github/src/publish.ts +++ b/extensions/github/src/publish.ts @@ -144,8 +144,6 @@ export async function publishRepository(gitAPI: GitAPI, repository?: Repository) } } - return; - const githubRepository = await vscode.window.withProgress({ location: vscode.ProgressLocation.Notification, cancellable: false, title: 'Publish to GitHub' }, async progress => { progress.report({ message: 'Publishing to GitHub private repository', increment: 25 }); From 88b1fa85e4d733c8727e5baf6ded0db3aa7a053d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Wed, 1 Jul 2020 11:13:23 +0200 Subject: [PATCH 08/93] fixes #100701 --- extensions/git/src/main.ts | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/extensions/git/src/main.ts b/extensions/git/src/main.ts index 5210aaa70f0ff..d541220ec3093 100644 --- a/extensions/git/src/main.ts +++ b/extensions/git/src/main.ts @@ -175,7 +175,7 @@ export async function activate(context: ExtensionContext): Promise return result; } -async function checkGitVersion(info: IGit): Promise { +async function checkGitv1(info: IGit): Promise { const config = workspace.getConfiguration('git'); const shouldIgnore = config.get('ignoreLegacyWarning') === true; @@ -202,3 +202,27 @@ async function checkGitVersion(info: IGit): Promise { await config.update('ignoreLegacyWarning', true, true); } } + +async function checkGitWindows(info: IGit): Promise { + if (!/^2\.(25|26)\./.test(info.version)) { + return; + } + + const update = localize('updateGit', "Update Git"); + const choice = await window.showWarningMessage( + localize('git2526', "There are known issues with the installed Git {0}. Please update to Git >= 2.27 for the git features to work correctly.", info.version), + update + ); + + if (choice === update) { + commands.executeCommand('vscode.open', Uri.parse('https://git-scm.com/')); + } +} + +async function checkGitVersion(info: IGit): Promise { + await checkGitv1(info); + + if (process.platform === 'win32') { + await checkGitWindows(info); + } +} From 52fd22b1205c9abe816ba24fc9d490f58f9da993 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Wed, 1 Jul 2020 11:28:22 +0200 Subject: [PATCH 09/93] fixes #99798 cc @roblourens for changes in settings --- src/vs/base/browser/ui/list/listWidget.ts | 1 + src/vs/platform/list/browser/listService.ts | 59 +++++++++++-------- .../preferences/browser/settingsTree.ts | 12 +++- 3 files changed, 46 insertions(+), 26 deletions(-) diff --git a/src/vs/base/browser/ui/list/listWidget.ts b/src/vs/base/browser/ui/list/listWidget.ts index 8664e20440056..d7e466466bd27 100644 --- a/src/vs/base/browser/ui/list/listWidget.ts +++ b/src/vs/base/browser/ui/list/listWidget.ts @@ -854,6 +854,7 @@ export interface IListOptions { readonly horizontalScrolling?: boolean; readonly additionalScrollHeight?: number; readonly transformOptimization?: boolean; + readonly smoothScrolling?: boolean; } export interface IListStyles { diff --git a/src/vs/platform/list/browser/listService.ts b/src/vs/platform/list/browser/listService.ts index 33c24f092c85e..586b2304f3c7b 100644 --- a/src/vs/platform/list/browser/listService.ts +++ b/src/vs/platform/list/browser/listService.ts @@ -179,6 +179,8 @@ function toWorkbenchListOptions(options: IListOptions, configurationServic } }; + result.smoothScrolling = configurationService.getValue(listSmoothScrolling); + return [result, disposables]; } @@ -193,7 +195,6 @@ export interface IWorkbenchListOptions extends IWorkbenchListOptionsUpdate, I export class WorkbenchList extends List { readonly contextKeyService: IContextKeyService; - private readonly configurationService: IConfigurationService; private readonly themeService: IThemeService; private listHasSelectionOrFocus: IContextKey; @@ -231,7 +232,6 @@ export class WorkbenchList extends List { this.disposables.add(workbenchListOptionsDisposable); this.contextKeyService = createScopedContextKeyService(contextKeyService, this); - this.configurationService = configurationService; this.themeService = themeService; const listSupportsMultiSelect = WorkbenchListSupportsMultiSelectContextKey.bindTo(this.contextKeyService); @@ -265,8 +265,25 @@ export class WorkbenchList extends List { this.listHasSelectionOrFocus.set(selection.length > 0 || focus.length > 0); })); + this.disposables.add(configurationService.onDidChangeConfiguration(e => { + if (e.affectsConfiguration(multiSelectModifierSettingKey)) { + this._useAltAsMultipleSelectionModifier = useAltAsMultipleSelectionModifier(configurationService); + } - this.registerListeners(); + let options: IListOptionsUpdate = {}; + + if (e.affectsConfiguration(horizontalScrollingKey) && this.horizontalScrolling === undefined) { + const horizontalScrolling = configurationService.getValue(horizontalScrollingKey); + options = { ...options, horizontalScrolling }; + } + if (e.affectsConfiguration(listSmoothScrolling)) { + const smoothScrolling = configurationService.getValue(listSmoothScrolling); + options = { ...options, smoothScrolling }; + } + if (Object.keys(options).length > 0) { + this.updateOptions(options); + } + })); } updateOptions(options: IWorkbenchListOptionsUpdate): void { @@ -292,18 +309,6 @@ export class WorkbenchList extends List { this._styler = attachListStyler(this, this.themeService, styles); } - private registerListeners(): void { - this.disposables.add(this.configurationService.onDidChangeConfiguration(e => { - if (e.affectsConfiguration(multiSelectModifierSettingKey)) { - this._useAltAsMultipleSelectionModifier = useAltAsMultipleSelectionModifier(this.configurationService); - } - if (e.affectsConfiguration(horizontalScrollingKey) && this.horizontalScrolling === undefined) { - const horizontalScrolling = this.configurationService.getValue(horizontalScrollingKey); - this.updateOptions({ horizontalScrolling }); - } - })); - } - get useAltAsMultipleSelectionModifier(): boolean { return this._useAltAsMultipleSelectionModifier; } @@ -316,7 +321,6 @@ export interface IWorkbenchPagedListOptions extends IWorkbenchListOptionsUpda export class WorkbenchPagedList extends PagedList { readonly contextKeyService: IContextKeyService; - private readonly configurationService: IConfigurationService; private readonly disposables: DisposableStore; @@ -350,7 +354,6 @@ export class WorkbenchPagedList extends PagedList { this.disposables.add(workbenchListOptionsDisposable); this.contextKeyService = createScopedContextKeyService(contextKeyService, this); - this.configurationService = configurationService; this.horizontalScrolling = options.horizontalScrolling; const listSupportsMultiSelect = WorkbenchListSupportsMultiSelectContextKey.bindTo(this.contextKeyService); @@ -365,17 +368,23 @@ export class WorkbenchPagedList extends PagedList { this.disposables.add(attachListStyler(this, themeService, options.overrideStyles)); } - this.registerListeners(); - } - - private registerListeners(): void { - this.disposables.add(this.configurationService.onDidChangeConfiguration(e => { + this.disposables.add(configurationService.onDidChangeConfiguration(e => { if (e.affectsConfiguration(multiSelectModifierSettingKey)) { - this._useAltAsMultipleSelectionModifier = useAltAsMultipleSelectionModifier(this.configurationService); + this._useAltAsMultipleSelectionModifier = useAltAsMultipleSelectionModifier(configurationService); } + + let options: IListOptionsUpdate = {}; + if (e.affectsConfiguration(horizontalScrollingKey) && this.horizontalScrolling === undefined) { - const horizontalScrolling = this.configurationService.getValue(horizontalScrollingKey); - this.updateOptions({ horizontalScrolling }); + const horizontalScrolling = configurationService.getValue(horizontalScrollingKey); + options = { ...options, horizontalScrolling }; + } + if (e.affectsConfiguration(listSmoothScrolling)) { + const smoothScrolling = configurationService.getValue(listSmoothScrolling); + options = { ...options, smoothScrolling }; + } + if (Object.keys(options).length > 0) { + this.updateOptions(options); } })); } diff --git a/src/vs/workbench/contrib/preferences/browser/settingsTree.ts b/src/vs/workbench/contrib/preferences/browser/settingsTree.ts index 8dd370fe7f25f..24f9042e00c01 100644 --- a/src/vs/workbench/contrib/preferences/browser/settingsTree.ts +++ b/src/vs/workbench/contrib/preferences/browser/settingsTree.ts @@ -1845,6 +1845,7 @@ export class SettingsTree extends ObjectTree { viewState: ISettingsEditorViewState, renderers: ITreeRenderer[], @IThemeService themeService: IThemeService, + @IConfigurationService configurationService: IConfigurationService, @IInstantiationService instantiationService: IInstantiationService, ) { super('SettingsTree', container, @@ -1870,7 +1871,8 @@ export class SettingsTree extends ObjectTree { } }, styleController: id => new DefaultStyleController(DOM.createStyleSheet(container), id), - filter: instantiationService.createInstance(SettingsTreeFilter, viewState) + filter: instantiationService.createInstance(SettingsTreeFilter, viewState), + smoothScrolling: configurationService.getValue('workbench.list.smoothScrolling'), }); this.disposables.clear(); @@ -1945,6 +1947,14 @@ export class SettingsTree extends ObjectTree { }, colors => { this.style(colors); })); + + this.disposables.add(configurationService.onDidChangeConfiguration(e => { + if (e.affectsConfiguration('workbench.list.smoothScrolling')) { + this.updateOptions({ + smoothScrolling: configurationService.getValue('workbench.list.smoothScrolling') + }); + } + })); } protected createModel(user: string, view: IList>, options: IObjectTreeOptions): ITreeModel { From 7729e9c0810a78bddd8cf760ebbdb28202e6b1ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Wed, 1 Jul 2020 11:30:39 +0200 Subject: [PATCH 10/93] fixes #100016 --- src/vs/workbench/contrib/update/browser/update.ts | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/src/vs/workbench/contrib/update/browser/update.ts b/src/vs/workbench/contrib/update/browser/update.ts index 50c3978dfe565..c328064ed42b6 100644 --- a/src/vs/workbench/contrib/update/browser/update.ts +++ b/src/vs/workbench/contrib/update/browser/update.ts @@ -16,7 +16,6 @@ import { IStorageService, StorageScope } from 'vs/platform/storage/common/storag import { IUpdateService, State as UpdateState, StateType, IUpdate } from 'vs/platform/update/common/update'; import * as semver from 'semver-umd'; import { INotificationService, Severity } from 'vs/platform/notification/common/notification'; -import { IDialogService } from 'vs/platform/dialogs/common/dialogs'; import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService'; import { ReleaseNotesManager } from './releaseNotesEditor'; import { isWindows } from 'vs/base/common/platform'; @@ -178,7 +177,6 @@ export class UpdateContribution extends Disposable implements IWorkbenchContribu @IStorageService private readonly storageService: IStorageService, @IInstantiationService private readonly instantiationService: IInstantiationService, @INotificationService private readonly notificationService: INotificationService, - @IDialogService private readonly dialogService: IDialogService, @IUpdateService private readonly updateService: IUpdateService, @IActivityService private readonly activityService: IActivityService, @IContextKeyService private readonly contextKeyService: IContextKeyService, @@ -277,11 +275,7 @@ export class UpdateContribution extends Disposable implements IWorkbenchContribu } private onUpdateNotAvailable(): void { - this.dialogService.show( - severity.Info, - nls.localize('noUpdatesAvailable', "There are currently no updates available."), - [nls.localize('ok', "OK")] - ); + this.notificationService.info(nls.localize('noUpdatesAvailable', "There are currently no updates available.")); } // linux From 921e66b0639830cd1f6182c67fd8f3ed701c6e17 Mon Sep 17 00:00:00 2001 From: isidor Date: Wed, 1 Jul 2020 12:01:09 +0200 Subject: [PATCH 11/93] fixes #100235 --- src/vs/workbench/contrib/debug/browser/repl.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/vs/workbench/contrib/debug/browser/repl.ts b/src/vs/workbench/contrib/debug/browser/repl.ts index acda4aad5d89c..4d76c06d720e7 100644 --- a/src/vs/workbench/contrib/debug/browser/repl.ts +++ b/src/vs/workbench/contrib/debug/browser/repl.ts @@ -610,6 +610,7 @@ export class Repl extends ViewPane implements IHistoryNavigationWidget { const clipboardText = await this.clipboardService.readText(); if (clipboardText) { this.replInput.setValue(this.replInput.getValue().concat(clipboardText)); + this.replInput.focus(); } })); actions.push(new Separator()); From 81ca3c25a14ae8e27c296ed67d336fa174b052d6 Mon Sep 17 00:00:00 2001 From: isidor Date: Wed, 1 Jul 2020 12:10:37 +0200 Subject: [PATCH 12/93] replPaste polish #100235 --- src/vs/workbench/contrib/debug/browser/repl.ts | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/debug/browser/repl.ts b/src/vs/workbench/contrib/debug/browser/repl.ts index 4d76c06d720e7..326bfb8c80c33 100644 --- a/src/vs/workbench/contrib/debug/browser/repl.ts +++ b/src/vs/workbench/contrib/debug/browser/repl.ts @@ -606,11 +606,17 @@ export class Repl extends ViewPane implements IHistoryNavigationWidget { await this.clipboardService.writeText(this.getVisibleContent()); return Promise.resolve(); })); - actions.push(new Action('debug.replPaste', localize('paste', "Paste"), undefined, true, async () => { + actions.push(new Action('debug.replPaste', localize('paste', "Paste"), undefined, this.debugService.state !== State.Inactive, async () => { const clipboardText = await this.clipboardService.readText(); if (clipboardText) { this.replInput.setValue(this.replInput.getValue().concat(clipboardText)); this.replInput.focus(); + const model = this.replInput.getModel(); + const lineNumber = model ? model.getLineCount() : 0; + const column = model?.getLineMaxColumn(lineNumber); + if (typeof lineNumber === 'number' && typeof column === 'number') { + this.replInput.setPosition({ lineNumber, column }); + } } })); actions.push(new Separator()); From 34928ddb604f65503715a5a0a426b9810db0a2f0 Mon Sep 17 00:00:00 2001 From: isidor Date: Wed, 1 Jul 2020 12:45:20 +0200 Subject: [PATCH 13/93] fixes #101434 --- src/vs/vscode.proposed.d.ts | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/vs/vscode.proposed.d.ts b/src/vs/vscode.proposed.d.ts index 5bb65b9adf557..4196af4833c99 100644 --- a/src/vs/vscode.proposed.d.ts +++ b/src/vs/vscode.proposed.d.ts @@ -830,10 +830,9 @@ declare module 'vscode' { noDebug?: boolean; /** - * Controls if the debug session created will be compacted with the parent in the CALL STACK view. - * Compact with the parent is only done if the session is the only child of it's parent session. - * Default is to compact. - * + * Controls if the debug session's parent session is shown in the CALL STACK view even if it has only a single child. + * By default, debug sessions with a single child are hidden in the CALL STACK view to make the tree more compact. + * If noCompact is true, then the debug session will never hide its parent. */ noCompact?: boolean; } From 199856707ffb829c1599a543215e888f30bacafe Mon Sep 17 00:00:00 2001 From: isidor Date: Wed, 1 Jul 2020 13:12:02 +0200 Subject: [PATCH 14/93] fixes #101442 --- src/vs/workbench/api/browser/mainThreadStatusBar.ts | 4 +++- src/vs/workbench/browser/parts/statusbar/statusbarPart.ts | 3 +++ src/vs/workbench/contrib/timeline/browser/timelinePane.ts | 6 ++++++ src/vs/workbench/services/statusbar/common/statusbar.ts | 6 ++++++ 4 files changed, 18 insertions(+), 1 deletion(-) diff --git a/src/vs/workbench/api/browser/mainThreadStatusBar.ts b/src/vs/workbench/api/browser/mainThreadStatusBar.ts index 09eff1450d0ad..d50bc8f08ebd3 100644 --- a/src/vs/workbench/api/browser/mainThreadStatusBar.ts +++ b/src/vs/workbench/api/browser/mainThreadStatusBar.ts @@ -30,12 +30,14 @@ export class MainThreadStatusBar implements MainThreadStatusBarShape { $setEntry(id: number, statusId: string, statusName: string, text: string, tooltip: string | undefined, command: Command | undefined, color: string | ThemeColor | undefined, alignment: MainThreadStatusBarAlignment, priority: number | undefined, accessibilityInformation: IAccessibilityInformation): void { // if there are icons in the text use the tooltip for the aria label let ariaLabel: string; + let role: string | undefined = undefined; if (accessibilityInformation) { ariaLabel = accessibilityInformation.label; + role = accessibilityInformation.role; } else { ariaLabel = text ? text.replace(MainThreadStatusBar.CODICON_REGEXP, (_match, codiconName) => codiconName) : ''; } - const entry: IStatusbarEntry = { text, tooltip, command, color, ariaLabel }; + const entry: IStatusbarEntry = { text, tooltip, command, color, ariaLabel, role }; if (typeof priority === 'undefined') { priority = 0; diff --git a/src/vs/workbench/browser/parts/statusbar/statusbarPart.ts b/src/vs/workbench/browser/parts/statusbar/statusbarPart.ts index fe6a54fcbcaa0..fd6e67fbc093f 100644 --- a/src/vs/workbench/browser/parts/statusbar/statusbarPart.ts +++ b/src/vs/workbench/browser/parts/statusbar/statusbarPart.ts @@ -765,6 +765,9 @@ class StatusbarEntryItem extends Disposable { this.container.setAttribute('aria-label', entry.ariaLabel); this.labelContainer.setAttribute('aria-label', entry.ariaLabel); } + if (!this.entry || entry.role !== this.entry.role) { + this.labelContainer.setAttribute('role', entry.role || 'button'); + } // Update: Tooltip (on the container, because label can be disabled) if (!this.entry || entry.tooltip !== this.entry.tooltip) { diff --git a/src/vs/workbench/contrib/timeline/browser/timelinePane.ts b/src/vs/workbench/contrib/timeline/browser/timelinePane.ts index 9eb51448f2255..7b07eae330332 100644 --- a/src/vs/workbench/contrib/timeline/browser/timelinePane.ts +++ b/src/vs/workbench/contrib/timeline/browser/timelinePane.ts @@ -885,6 +885,12 @@ export class TimelinePane extends ViewPane { } return element.accessibilityInformation ? element.accessibilityInformation.label : localize('timeline.aria.item', "{0}: {1}", element.relativeTime ?? '', element.label); }, + getRole(element: TreeElement): string { + if (isLoadMoreCommand(element)) { + return 'treeitem'; + } + return element.accessibilityInformation && element.accessibilityInformation.role ? element.accessibilityInformation.role : 'treeitem'; + }, getWidgetAriaLabel(): string { return localize('timeline', "Timeline"); } diff --git a/src/vs/workbench/services/statusbar/common/statusbar.ts b/src/vs/workbench/services/statusbar/common/statusbar.ts index 018a049fa47db..14a52e61d68e8 100644 --- a/src/vs/workbench/services/statusbar/common/statusbar.ts +++ b/src/vs/workbench/services/statusbar/common/statusbar.ts @@ -33,6 +33,12 @@ export interface IStatusbarEntry { */ readonly ariaLabel: string; + /** + * Role of the status bar entry which defines how a screen reader interacts with it. + * Default is 'button'. + */ + readonly role?: string; + /** * An optional tooltip text to show when you hover over the entry */ From 0be0ebec5db00b13cabcee3663722dc83be98674 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Wed, 1 Jul 2020 14:12:51 +0200 Subject: [PATCH 15/93] Fix #97150 --- src/vs/workbench/contrib/userDataSync/browser/userDataSync.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/contrib/userDataSync/browser/userDataSync.ts b/src/vs/workbench/contrib/userDataSync/browser/userDataSync.ts index 61bd28a78d1e1..a7db7c25c79f3 100644 --- a/src/vs/workbench/contrib/userDataSync/browser/userDataSync.ts +++ b/src/vs/workbench/contrib/userDataSync/browser/userDataSync.ts @@ -75,10 +75,10 @@ const syncNowCommand = { title: localize('sync now', "Preferences Sync: Sync Now"), description(userDataSyncService: IUserDataSyncService): string | undefined { if (userDataSyncService.status === SyncStatus.Syncing) { - return localize('sync is on with syncing', "syncing"); + return localize('syncing', "syncing"); } if (userDataSyncService.lastSyncTime) { - return localize('sync is on with time', "synced {0}", fromNow(userDataSyncService.lastSyncTime, true)); + return localize('synced with time', "synced {0}", fromNow(userDataSyncService.lastSyncTime, true)); } return undefined; } From f9c46ad5538e19396ef125ca0ba5e1b700873686 Mon Sep 17 00:00:00 2001 From: isidor Date: Wed, 1 Jul 2020 14:14:31 +0200 Subject: [PATCH 16/93] fixes #101351 --- src/vs/workbench/contrib/debug/browser/media/debugViewlet.css | 1 + 1 file changed, 1 insertion(+) diff --git a/src/vs/workbench/contrib/debug/browser/media/debugViewlet.css b/src/vs/workbench/contrib/debug/browser/media/debugViewlet.css index afb977b5c1bc1..3ab3a5c63efe8 100644 --- a/src/vs/workbench/contrib/debug/browser/media/debugViewlet.css +++ b/src/vs/workbench/contrib/debug/browser/media/debugViewlet.css @@ -142,6 +142,7 @@ .debug-pane .debug-call-stack .monaco-list-row .monaco-action-bar { display: none; flex-shrink: 0; + margin-right: 1px; } .debug-pane .debug-call-stack .monaco-list-row:hover .monaco-action-bar { From daa72ed3933ffb5699a958774a30e003f5059714 Mon Sep 17 00:00:00 2001 From: Alex Ross Date: Wed, 1 Jul 2020 14:14:25 +0200 Subject: [PATCH 17/93] Fix task id for custom execution tasks Fixes #101412 --- src/vs/workbench/api/browser/mainThreadTask.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/api/browser/mainThreadTask.ts b/src/vs/workbench/api/browser/mainThreadTask.ts index a51b71d9fb2d4..8e93c7cfa6add 100644 --- a/src/vs/workbench/api/browser/mainThreadTask.ts +++ b/src/vs/workbench/api/browser/mainThreadTask.ts @@ -368,7 +368,7 @@ namespace TaskDTO { const label = nls.localize('task.label', '{0}: {1}', source.label, task.name); const definition = TaskDefinitionDTO.to(task.definition, executeOnly)!; - const id = `${task.source.extensionId}.${definition._key}`; + const id = (CustomExecutionDTO.is(task.execution!) && task._id) ? task._id : `${task.source.extensionId}.${definition._key}`; const result: ContributedTask = new ContributedTask( id, // uuidMap.getUUID(identifier) source, From 6b5173f0ee0e2de51aa2d90a928cd0fc4eae08ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Wed, 1 Jul 2020 15:13:09 +0200 Subject: [PATCH 18/93] fixes #101055 --- .../workbench/contrib/scm/browser/scmViewPane.ts | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/vs/workbench/contrib/scm/browser/scmViewPane.ts b/src/vs/workbench/contrib/scm/browser/scmViewPane.ts index 1216599ff5781..b19c4f771f7bd 100644 --- a/src/vs/workbench/contrib/scm/browser/scmViewPane.ts +++ b/src/vs/workbench/contrib/scm/browser/scmViewPane.ts @@ -47,7 +47,7 @@ import { flatten } from 'vs/base/common/arrays'; import { memoize } from 'vs/base/common/decorators'; import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage'; import { toResource, SideBySideEditor } from 'vs/workbench/common/editor'; -import { SIDE_BAR_BACKGROUND, SIDE_BAR_BORDER, PANEL_BACKGROUND } from 'vs/workbench/common/theme'; +import { SIDE_BAR_BACKGROUND, SIDE_BAR_BORDER, PANEL_BACKGROUND, PANEL_INPUT_BORDER } from 'vs/workbench/common/theme'; import { CodeEditorWidget, ICodeEditorWidgetOptions } from 'vs/editor/browser/widget/codeEditorWidget'; import { ITextModel } from 'vs/editor/common/model'; import { IEditorConstructionOptions } from 'vs/editor/common/config/editorOptions'; @@ -1774,7 +1774,7 @@ registerThemingParticipant((theme, collector) => { collector.addRule(`.scm-view .scm-editor-container .monaco-editor-background, .scm-view .scm-editor-container .monaco-editor, .scm-view .scm-editor-container .monaco-editor .margin - { background-color: ${inputBackgroundColor}; }`); + { background-color: ${inputBackgroundColor} !important; }`); } const inputForegroundColor = theme.getColor(inputForeground); @@ -1787,6 +1787,11 @@ registerThemingParticipant((theme, collector) => { collector.addRule(`.scm-view .scm-editor-container { outline: 1px solid ${inputBorderColor}; }`); } + const panelInputBorder = theme.getColor(PANEL_INPUT_BORDER); + if (panelInputBorder) { + collector.addRule(`.monaco-workbench .part.panel .scm-view .scm-editor-container { outline: 1px solid ${panelInputBorder}; }`); + } + const focusBorderColor = theme.getColor(focusBorder); if (focusBorderColor) { collector.addRule(`.scm-view .scm-editor-container.synthetic-focus { outline: 1px solid ${focusBorderColor}; }`); @@ -1799,7 +1804,7 @@ registerThemingParticipant((theme, collector) => { const inputValidationInfoBorderColor = theme.getColor(inputValidationInfoBorder); if (inputValidationInfoBorderColor) { - collector.addRule(`.scm-view .scm-editor-container.validation-info { outline: 1px solid ${inputValidationInfoBorderColor}; }`); + collector.addRule(`.scm-view .scm-editor-container.validation-info { outline: 1px solid ${inputValidationInfoBorderColor} !important; }`); collector.addRule(`.scm-editor-validation.validation-info { border-color: ${inputValidationInfoBorderColor}; }`); } @@ -1815,7 +1820,7 @@ registerThemingParticipant((theme, collector) => { const inputValidationWarningBorderColor = theme.getColor(inputValidationWarningBorder); if (inputValidationWarningBorderColor) { - collector.addRule(`.scm-view .scm-editor-container.validation-warning { outline: 1px solid ${inputValidationWarningBorderColor}; }`); + collector.addRule(`.scm-view .scm-editor-container.validation-warning { outline: 1px solid ${inputValidationWarningBorderColor} !important; }`); collector.addRule(`.scm-editor-validation.validation-warning { border-color: ${inputValidationWarningBorderColor}; }`); } @@ -1831,7 +1836,7 @@ registerThemingParticipant((theme, collector) => { const inputValidationErrorBorderColor = theme.getColor(inputValidationErrorBorder); if (inputValidationErrorBorderColor) { - collector.addRule(`.scm-view .scm-editor-container.validation-error { outline: 1px solid ${inputValidationErrorBorderColor}; }`); + collector.addRule(`.scm-view .scm-editor-container.validation-error { outline: 1px solid ${inputValidationErrorBorderColor} !important; }`); collector.addRule(`.scm-editor-validation.validation-error { border-color: ${inputValidationErrorBorderColor}; }`); } From 0456ff932ec645745e1c4023c80df8fa6b9c477d Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Wed, 1 Jul 2020 15:13:16 +0200 Subject: [PATCH 19/93] Fix #101339 --- .../test/node/configurationService.test.ts | 214 +++++++----------- 1 file changed, 82 insertions(+), 132 deletions(-) diff --git a/src/vs/platform/configuration/test/node/configurationService.test.ts b/src/vs/platform/configuration/test/node/configurationService.test.ts index f5fb471fcdb2c..2df13d8c9b6a8 100644 --- a/src/vs/platform/configuration/test/node/configurationService.test.ts +++ b/src/vs/platform/configuration/test/node/configurationService.test.ts @@ -4,179 +4,142 @@ *--------------------------------------------------------------------------------------------*/ import * as assert from 'assert'; -import * as os from 'os'; -import * as path from 'vs/base/common/path'; -import * as fs from 'fs'; import { Registry } from 'vs/platform/registry/common/platform'; import { ConfigurationService } from 'vs/platform/configuration/common/configurationService'; -import * as uuid from 'vs/base/common/uuid'; import { IConfigurationRegistry, Extensions as ConfigurationExtensions } from 'vs/platform/configuration/common/configurationRegistry'; -import { testFile } from 'vs/base/test/node/utils'; +import { testFile, ITestFileResult } from 'vs/base/test/node/utils'; import { URI } from 'vs/base/common/uri'; import { ConfigurationTarget } from 'vs/platform/configuration/common/configuration'; import { Event } from 'vs/base/common/event'; import { NullLogService } from 'vs/platform/log/common/log'; import { FileService } from 'vs/platform/files/common/fileService'; -import { IDisposable } from 'vs/base/common/lifecycle'; -import { DiskFileSystemProvider } from 'vs/platform/files/node/diskFileSystemProvider'; +import { DisposableStore } from 'vs/base/common/lifecycle'; import { Schemas } from 'vs/base/common/network'; import { IFileService } from 'vs/platform/files/common/files'; import { VSBuffer } from 'vs/base/common/buffer'; +import { InMemoryFileSystemProvider } from 'vs/platform/files/common/inMemoryFilesystemProvider'; suite('ConfigurationService - Node', () => { let fileService: IFileService; - const disposables: IDisposable[] = []; - - setup(() => { - const logService = new NullLogService(); - fileService = new FileService(logService); - disposables.push(fileService); - const diskFileSystemProvider = new DiskFileSystemProvider(logService); - disposables.push(diskFileSystemProvider); + let testFileResult: ITestFileResult; + let settingsResource: URI; + const disposables: DisposableStore = new DisposableStore(); + + setup(async () => { + fileService = new FileService(new NullLogService()); + disposables.add(fileService); + const diskFileSystemProvider = new InMemoryFileSystemProvider(); + disposables.add(diskFileSystemProvider); fileService.registerProvider(Schemas.file, diskFileSystemProvider); + testFileResult = await testFile('config', 'config.json'); + settingsResource = URI.file(testFileResult.testFile); }); - test('simple', async () => { - const res = await testFile('config', 'config.json'); - fs.writeFileSync(res.testFile, '{ "foo": "bar" }'); + teardown(async () => { + disposables.clear(); + await testFileResult.cleanUp(); + }); - const service = new ConfigurationService(URI.file(res.testFile), fileService); - await service.initialize(); - const config = service.getValue<{ + test('simple', async () => { + await fileService.writeFile(settingsResource, VSBuffer.fromString('{ "foo": "bar" }')); + const testObject = disposables.add(new ConfigurationService(settingsResource, fileService)); + await testObject.initialize(); + const config = testObject.getValue<{ foo: string; }>(); assert.ok(config); assert.equal(config.foo, 'bar'); - service.dispose(); - - return res.cleanUp(); }); test('config gets flattened', async () => { - const res = await testFile('config', 'config.json'); + await fileService.writeFile(settingsResource, VSBuffer.fromString('{ "testworkbench.editor.tabs": true }')); - fs.writeFileSync(res.testFile, '{ "testworkbench.editor.tabs": true }'); - - const service = new ConfigurationService(URI.file(res.testFile), fileService); - await service.initialize(); - const config = service.getValue<{ + const testObject = disposables.add(new ConfigurationService(settingsResource, fileService)); + await testObject.initialize(); + const config = testObject.getValue<{ testworkbench: { editor: { tabs: boolean; }; }; }>(); + assert.ok(config); assert.ok(config.testworkbench); assert.ok(config.testworkbench.editor); assert.equal(config.testworkbench.editor.tabs, true); - - service.dispose(); - return res.cleanUp(); }); test('error case does not explode', async () => { - const res = await testFile('config', 'config.json'); + await fileService.writeFile(settingsResource, VSBuffer.fromString(',,,,')); - fs.writeFileSync(res.testFile, ',,,,'); - - const service = new ConfigurationService(URI.file(res.testFile), fileService); - await service.initialize(); - const config = service.getValue<{ + const testObject = disposables.add(new ConfigurationService(settingsResource, fileService)); + await testObject.initialize(); + const config = testObject.getValue<{ foo: string; }>(); - assert.ok(config); - service.dispose(); - return res.cleanUp(); + assert.ok(config); }); test('missing file does not explode', async () => { - const id = uuid.generateUuid(); - const parentDir = path.join(os.tmpdir(), 'vsctests', id); - const newDir = path.join(parentDir, 'config', id); - const testFile = path.join(newDir, 'config.json'); + const testObject = disposables.add(new ConfigurationService(URI.file('__testFile'), fileService)); + await testObject.initialize(); - const service = new ConfigurationService(URI.file(testFile), fileService); - await service.initialize(); + const config = testObject.getValue<{ foo: string }>(); - const config = service.getValue<{ foo: string }>(); assert.ok(config); - - service.dispose(); }); test('trigger configuration change event when file does not exist', async () => { - const res = await testFile('config', 'config.json'); - const settingsFile = URI.file(res.testFile); - const service = new ConfigurationService(settingsFile, fileService); - await service.initialize(); + const testObject = disposables.add(new ConfigurationService(settingsResource, fileService)); + await testObject.initialize(); return new Promise(async (c, e) => { - const disposable = Event.filter(service.onDidChangeConfiguration, e => e.source === ConfigurationTarget.USER)(async (e) => { - disposable.dispose(); - assert.equal(service.getValue('foo'), 'bar'); - service.dispose(); - await res.cleanUp(); + disposables.add(Event.filter(testObject.onDidChangeConfiguration, e => e.source === ConfigurationTarget.USER)(() => { + assert.equal(testObject.getValue('foo'), 'bar'); c(); - }); - await fileService.writeFile(settingsFile, VSBuffer.fromString('{ "foo": "bar" }')); + })); + await fileService.writeFile(settingsResource, VSBuffer.fromString('{ "foo": "bar" }')); }); }); test('trigger configuration change event when file exists', async () => { - const res = await testFile('config', 'config.json'); + const testObject = disposables.add(new ConfigurationService(settingsResource, fileService)); + await fileService.writeFile(settingsResource, VSBuffer.fromString('{ "foo": "bar" }')); + await testObject.initialize(); - const service = new ConfigurationService(URI.file(res.testFile), fileService); - fs.writeFileSync(res.testFile, '{ "foo": "bar" }'); - await service.initialize(); return new Promise((c, e) => { - const disposable = Event.filter(service.onDidChangeConfiguration, e => e.source === ConfigurationTarget.USER)(async (e) => { - disposable.dispose(); - assert.equal(service.getValue('foo'), 'barz'); - service.dispose(); - await res.cleanUp(); + disposables.add(Event.filter(testObject.onDidChangeConfiguration, e => e.source === ConfigurationTarget.USER)(async (e) => { + assert.equal(testObject.getValue('foo'), 'barz'); c(); - }); - fs.writeFileSync(res.testFile, '{ "foo": "barz" }'); + })); + fileService.writeFile(settingsResource, VSBuffer.fromString('{ "foo": "barz" }')); }); - }); test('reloadConfiguration', async () => { - const res = await testFile('config', 'config.json'); - - fs.writeFileSync(res.testFile, '{ "foo": "bar" }'); + await fileService.writeFile(settingsResource, VSBuffer.fromString('{ "foo": "bar" }')); - const service = new ConfigurationService(URI.file(res.testFile), fileService); - await service.initialize(); - let config = service.getValue<{ - foo: string; - }>(); - assert.ok(config); - assert.equal(config.foo, 'bar'); - fs.writeFileSync(res.testFile, '{ "foo": "changed" }'); - - // still outdated - config = service.getValue<{ + const testObject = disposables.add(new ConfigurationService(settingsResource, fileService)); + await testObject.initialize(); + let config = testObject.getValue<{ foo: string; }>(); assert.ok(config); assert.equal(config.foo, 'bar'); + await fileService.writeFile(settingsResource, VSBuffer.fromString('{ "foo": "changed" }')); // force a reload to get latest - await service.reloadConfiguration(); - config = service.getValue<{ + await testObject.reloadConfiguration(); + config = testObject.getValue<{ foo: string; }>(); assert.ok(config); assert.equal(config.foo, 'changed'); - - service.dispose(); - return res.cleanUp(); }); test('model defaults', async () => { @@ -200,33 +163,27 @@ suite('ConfigurationService - Node', () => { } }); - let serviceWithoutFile = new ConfigurationService(URI.file('__testFile'), fileService); - await serviceWithoutFile.initialize(); - let setting = serviceWithoutFile.getValue(); + let testObject = disposables.add(new ConfigurationService(URI.file('__testFile'), fileService)); + await testObject.initialize(); + let setting = testObject.getValue(); assert.ok(setting); assert.equal(setting.configuration.service.testSetting, 'isSet'); - return testFile('config', 'config.json').then(async res => { - fs.writeFileSync(res.testFile, '{ "testworkbench.editor.tabs": true }'); + await fileService.writeFile(settingsResource, VSBuffer.fromString('{ "testworkbench.editor.tabs": true }')); + testObject = disposables.add(new ConfigurationService(settingsResource, fileService)); - const service = new ConfigurationService(URI.file(res.testFile), fileService); + setting = testObject.getValue(); - let setting = service.getValue(); - - assert.ok(setting); - assert.equal(setting.configuration.service.testSetting, 'isSet'); + assert.ok(setting); + assert.equal(setting.configuration.service.testSetting, 'isSet'); - fs.writeFileSync(res.testFile, '{ "configuration.service.testSetting": "isChanged" }'); + await fileService.writeFile(settingsResource, VSBuffer.fromString('{ "configuration.service.testSetting": "isChanged" }')); - await service.reloadConfiguration(); - let setting_1 = service.getValue(); - assert.ok(setting_1); - assert.equal(setting_1.configuration.service.testSetting, 'isChanged'); - service.dispose(); - serviceWithoutFile.dispose(); - return res.cleanUp(); - }); + await testObject.reloadConfiguration(); + setting = testObject.getValue(); + assert.ok(setting); + assert.equal(setting.configuration.service.testSetting, 'isChanged'); }); test('lookup', async () => { @@ -242,30 +199,27 @@ suite('ConfigurationService - Node', () => { } }); - const r = await testFile('config', 'config.json'); - const service = new ConfigurationService(URI.file(r.testFile), fileService); - service.initialize(); + const testObject = disposables.add(new ConfigurationService(settingsResource, fileService)); + testObject.initialize(); - let res = service.inspect('something.missing'); + let res = testObject.inspect('something.missing'); assert.strictEqual(res.value, undefined); assert.strictEqual(res.defaultValue, undefined); assert.strictEqual(res.userValue, undefined); - res = service.inspect('lookup.service.testSetting'); + res = testObject.inspect('lookup.service.testSetting'); assert.strictEqual(res.defaultValue, 'isSet'); assert.strictEqual(res.value, 'isSet'); assert.strictEqual(res.userValue, undefined); - fs.writeFileSync(r.testFile, '{ "lookup.service.testSetting": "bar" }'); + await fileService.writeFile(settingsResource, VSBuffer.fromString('{ "lookup.service.testSetting": "bar" }')); - await service.reloadConfiguration(); - res = service.inspect('lookup.service.testSetting'); + await testObject.reloadConfiguration(); + res = testObject.inspect('lookup.service.testSetting'); assert.strictEqual(res.defaultValue, 'isSet'); assert.strictEqual(res.userValue, 'bar'); assert.strictEqual(res.value, 'bar'); - service.dispose(); - return r.cleanUp(); }); test('lookup with null', async () => { @@ -280,25 +234,21 @@ suite('ConfigurationService - Node', () => { } }); - const r = await testFile('config', 'config.json'); - const service = new ConfigurationService(URI.file(r.testFile), fileService); - service.initialize(); + const testObject = disposables.add(new ConfigurationService(settingsResource, fileService)); + testObject.initialize(); - let res = service.inspect('lookup.service.testNullSetting'); + let res = testObject.inspect('lookup.service.testNullSetting'); assert.strictEqual(res.defaultValue, null); assert.strictEqual(res.value, null); assert.strictEqual(res.userValue, undefined); - fs.writeFileSync(r.testFile, '{ "lookup.service.testNullSetting": null }'); + await fileService.writeFile(settingsResource, VSBuffer.fromString('{ "lookup.service.testNullSetting": null }')); - await service.reloadConfiguration(); + await testObject.reloadConfiguration(); - res = service.inspect('lookup.service.testNullSetting'); + res = testObject.inspect('lookup.service.testNullSetting'); assert.strictEqual(res.defaultValue, null); assert.strictEqual(res.value, null); assert.strictEqual(res.userValue, null); - - service.dispose(); - return r.cleanUp(); }); }); From b15f21b693bdb2211b65ee8c8a1e56e187d91f1f Mon Sep 17 00:00:00 2001 From: isidor Date: Wed, 1 Jul 2020 15:27:04 +0200 Subject: [PATCH 20/93] fixes #101431 --- src/vs/workbench/contrib/debug/browser/callStackView.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/vs/workbench/contrib/debug/browser/callStackView.ts b/src/vs/workbench/contrib/debug/browser/callStackView.ts index 23a5290275c60..7e27b4b03d550 100644 --- a/src/vs/workbench/contrib/debug/browser/callStackView.ts +++ b/src/vs/workbench/contrib/debug/browser/callStackView.ts @@ -355,6 +355,10 @@ export class CallStackView extends ViewPane { const sessionListeners: IDisposable[] = []; sessionListeners.push(s.onDidChangeName(() => this.tree.rerender(s))); sessionListeners.push(s.onDidEndAdapter(() => dispose(sessionListeners))); + if (s.parentSession) { + // A session we already expanded has a new child session, allow to expand it again. + this.autoExpandedSessions.delete(s.parentSession); + } })); } From 72ea6f6d75b4d95698bda667002c749c67104fba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Wed, 1 Jul 2020 15:29:55 +0200 Subject: [PATCH 21/93] fixes #101251 --- src/vs/workbench/contrib/scm/browser/media/scm.css | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/vs/workbench/contrib/scm/browser/media/scm.css b/src/vs/workbench/contrib/scm/browser/media/scm.css index a28ce51d3fe2c..972b4de20322f 100644 --- a/src/vs/workbench/contrib/scm/browser/media/scm.css +++ b/src/vs/workbench/contrib/scm/browser/media/scm.css @@ -47,18 +47,19 @@ } .scm-view .scm-provider > .actions .monaco-action-bar .action-item { - margin-left: 4px; - text-overflow: ellipsis; + padding-left: 4px; display: flex; align-items: center; - min-width: 14px; + min-width: 16px; } .scm-view .scm-provider > .actions .monaco-action-bar .action-label { - text-overflow: ellipsis; + display: flex; + align-items: center; overflow: hidden; - min-width: 14px; /* for flex */ + min-width: 16px; /* for flex */ height: 100%; + margin: 0; } .scm-view .scm-provider > .actions .monaco-action-bar .action-label .codicon { From dbfc5dd2fead3c220df8d680d5f0533cb2f3aa35 Mon Sep 17 00:00:00 2001 From: Alex Ross Date: Wed, 1 Jul 2020 15:33:19 +0200 Subject: [PATCH 22/93] Make platform warning more specific for dialog title Fixes #101443 --- src/vs/vscode.d.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/vs/vscode.d.ts b/src/vs/vscode.d.ts index d4a0d5d8dfce2..7d8e42b70fc2e 100644 --- a/src/vs/vscode.d.ts +++ b/src/vs/vscode.d.ts @@ -1734,8 +1734,8 @@ declare module 'vscode' { /** * Dialog title. * - * Depending on the underlying operating system this parameter might be ignored, since some - * systems do not present title on open dialogs. + * This parameter might be ignored, as not all operating systems display a title on open dialogs + * (for example, macOS). */ title?: string; } @@ -1769,8 +1769,8 @@ declare module 'vscode' { /** * Dialog title. * - * Depending on the underlying operating system this parameter might be ignored, since some - * systems do not present title on save dialogs. + * This parameter might be ignored, as not all operating systems display a title on save dialogs + * (for example, macOS). */ title?: string; } From cac8f2e908fa4f052336bae7dce6b0540b407b4b Mon Sep 17 00:00:00 2001 From: Anoesj Sadraee Date: Wed, 1 Jul 2020 15:36:37 +0200 Subject: [PATCH 23/93] Add 'pnpm' option to NPM scripts (#100654) Co-authored-by: Alex Ross --- extensions/npm/README.md | 2 +- extensions/npm/package.json | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/extensions/npm/README.md b/extensions/npm/README.md index f3707f85d32a7..144cdd275384f 100644 --- a/extensions/npm/README.md +++ b/extensions/npm/README.md @@ -34,7 +34,7 @@ The extension fetches data from https://registry.npmjs.org and https://registry. - `npm.autoDetect` - Enable detecting scripts as tasks, the default is `on`. - `npm.runSilent` - Run npm script with the `--silent` option, the default is `false`. -- `npm.packageManager` - The package manager used to run the scripts: `npm` or `yarn`, the default is `npm`. +- `npm.packageManager` - The package manager used to run the scripts: `npm`, `yarn` or `pnpm`, the default is `npm`. - `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`. diff --git a/extensions/npm/package.json b/extensions/npm/package.json index d85a042b267e4..b4f8c69726ffd 100644 --- a/extensions/npm/package.json +++ b/extensions/npm/package.json @@ -215,7 +215,8 @@ "type": "string", "enum": [ "npm", - "yarn" + "yarn", + "pnpm" ], "default": "npm", "description": "%config.npm.packageManager%" From 35a4b2304229fd4b002a4521aef4a72d4a6ed6d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Wed, 1 Jul 2020 15:42:19 +0200 Subject: [PATCH 24/93] add scm label related to #101103 --- src/vs/workbench/contrib/scm/browser/media/scm.css | 6 ++++++ src/vs/workbench/contrib/scm/browser/scmViewPane.ts | 6 +++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/scm/browser/media/scm.css b/src/vs/workbench/contrib/scm/browser/media/scm.css index 972b4de20322f..61dc3b4fecfbf 100644 --- a/src/vs/workbench/contrib/scm/browser/media/scm.css +++ b/src/vs/workbench/contrib/scm/browser/media/scm.css @@ -39,6 +39,12 @@ overflow: hidden; } +.scm-view .scm-provider > .label > .description { + opacity: 0.7; + margin-left: 0.5em; + font-size: 0.9em; +} + .scm-view .scm-provider > .actions { flex: 1; padding-left: 10px; diff --git a/src/vs/workbench/contrib/scm/browser/scmViewPane.ts b/src/vs/workbench/contrib/scm/browser/scmViewPane.ts index b19c4f771f7bd..a5e07cfdfbd52 100644 --- a/src/vs/workbench/contrib/scm/browser/scmViewPane.ts +++ b/src/vs/workbench/contrib/scm/browser/scmViewPane.ts @@ -151,6 +151,7 @@ interface ISCMLayout { interface RepositoryTemplate { readonly name: HTMLElement; + readonly description: HTMLElement; readonly countContainer: HTMLElement; readonly count: CountBadge; readonly toolBar: ToolBar; @@ -178,6 +179,7 @@ class RepositoryRenderer implements ICompressibleTreeRenderer, index: number, templateData: RepositoryTemplate, height: number | undefined): void { @@ -199,8 +201,10 @@ class RepositoryRenderer implements ICompressibleTreeRenderer Date: Wed, 1 Jul 2020 06:42:55 -0700 Subject: [PATCH 25/93] Require ctrl on link provider link Fixes #101473 --- .../browser/links/terminalExternalLinkProviderAdapter.ts | 5 ++++- .../contrib/terminal/browser/links/terminalLinkManager.ts | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/contrib/terminal/browser/links/terminalExternalLinkProviderAdapter.ts b/src/vs/workbench/contrib/terminal/browser/links/terminalExternalLinkProviderAdapter.ts index 6eb7c6b1ff1d1..aa8f0f670af3b 100644 --- a/src/vs/workbench/contrib/terminal/browser/links/terminalExternalLinkProviderAdapter.ts +++ b/src/vs/workbench/contrib/terminal/browser/links/terminalExternalLinkProviderAdapter.ts @@ -9,6 +9,7 @@ import { TerminalLink } from 'vs/workbench/contrib/terminal/browser/links/termin import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { TerminalBaseLinkProvider } from 'vs/workbench/contrib/terminal/browser/links/terminalBaseLinkProvider'; import { ITerminalExternalLinkProvider, ITerminalInstance } from 'vs/workbench/contrib/terminal/browser/terminal'; +import { XtermLinkMatcherHandler } from 'vs/workbench/contrib/terminal/browser/links/terminalLinkManager'; /** * An adapter to convert a simple external link provider into an internal link provider that @@ -20,6 +21,7 @@ export class TerminalExternalLinkProviderAdapter extends TerminalBaseLinkProvide private readonly _xterm: Terminal, private readonly _instance: ITerminalInstance, private readonly _externalLinkProvider: ITerminalExternalLinkProvider, + private readonly _wrapLinkHandler: (handler: (event: MouseEvent | undefined, link: string) => void) => XtermLinkMatcherHandler, private readonly _tooltipCallback: (link: TerminalLink, viewportRange: IViewportRange, modifierDownCallback?: () => void, modifierUpCallback?: () => void) => void, @IInstantiationService private readonly _instantiationService: IInstantiationService ) { @@ -58,7 +60,8 @@ export class TerminalExternalLinkProviderAdapter extends TerminalBaseLinkProvide endLineNumber: 1 }, startLine); const matchingText = lineContent.substr(link.startIndex, link.length) || ''; - return this._instantiationService.createInstance(TerminalLink, bufferRange, matchingText, this._xterm.buffer.active.viewportY, (_, text) => link.activate(text), this._tooltipCallback, true, link.label); + const activateLink = this._wrapLinkHandler((_, text) => link.activate(text)); + return this._instantiationService.createInstance(TerminalLink, bufferRange, matchingText, this._xterm.buffer.active.viewportY, activateLink, this._tooltipCallback, true, link.label); }); } } diff --git a/src/vs/workbench/contrib/terminal/browser/links/terminalLinkManager.ts b/src/vs/workbench/contrib/terminal/browser/links/terminalLinkManager.ts index cfb59efb2bf27..64434e1354850 100644 --- a/src/vs/workbench/contrib/terminal/browser/links/terminalLinkManager.ts +++ b/src/vs/workbench/contrib/terminal/browser/links/terminalLinkManager.ts @@ -156,7 +156,7 @@ export class TerminalLinkManager extends DisposableStore { } public registerExternalLinkProvider(instance: ITerminalInstance, linkProvider: ITerminalExternalLinkProvider): IDisposable { - const wrappedLinkProvider = this._instantiationService.createInstance(TerminalExternalLinkProviderAdapter, this._xterm, instance, linkProvider, this._tooltipCallback2.bind(this)); + const wrappedLinkProvider = this._instantiationService.createInstance(TerminalExternalLinkProviderAdapter, this._xterm, instance, linkProvider, this._wrapLinkHandler.bind(this), this._tooltipCallback2.bind(this)); const newLinkProvider = this._xterm.registerLinkProvider(wrappedLinkProvider); // Re-register the standard link providers so they are a lower priority that the new one this._registerStandardLinkProviders(); From baa0bfcf68a54f05ff95566e8395e2217784a478 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Wed, 1 Jul 2020 15:37:24 +0200 Subject: [PATCH 26/93] Fix #98865 --- .../browser/parts/views/viewsService.ts | 5 +++ src/vs/workbench/common/views.ts | 1 + .../browser/extensions.contribution.ts | 3 +- .../extensions/browser/extensionsActions.ts | 39 ++++++++++++------- .../test/browser/workbenchTestServices.ts | 1 + 5 files changed, 35 insertions(+), 14 deletions(-) diff --git a/src/vs/workbench/browser/parts/views/viewsService.ts b/src/vs/workbench/browser/parts/views/viewsService.ts index 979f71c9bcb22..b7ae7fe9eb99b 100644 --- a/src/vs/workbench/browser/parts/views/viewsService.ts +++ b/src/vs/workbench/browser/parts/views/viewsService.ts @@ -275,6 +275,11 @@ export class ViewsService extends Disposable implements IViewsService { return viewContainerId ? this.viewDescriptorService.getViewContainerById(viewContainerId) : null; } + getActiveViewPaneContainerWithId(viewContainerId: string): IViewPaneContainer | null { + const viewContainer = this.viewDescriptorService.getViewContainerById(viewContainerId); + return viewContainer ? this.getActiveViewPaneContainer(viewContainer) : null; + } + async openViewContainer(id: string, focus?: boolean): Promise { const viewContainer = this.viewDescriptorService.getViewContainerById(id); if (viewContainer) { diff --git a/src/vs/workbench/common/views.ts b/src/vs/workbench/common/views.ts index 6a22b6c238783..9c8e2795336f7 100644 --- a/src/vs/workbench/common/views.ts +++ b/src/vs/workbench/common/views.ts @@ -484,6 +484,7 @@ export interface IViewsService { openViewContainer(id: string, focus?: boolean): Promise; closeViewContainer(id: string): void; getVisibleViewContainer(location: ViewContainerLocation): ViewContainer | null; + getActiveViewPaneContainerWithId(viewContainerId: string): IViewPaneContainer | null; // View APIs readonly onDidChangeViewVisibility: Event<{ id: string, visible: boolean }>; diff --git a/src/vs/workbench/contrib/extensions/browser/extensions.contribution.ts b/src/vs/workbench/contrib/extensions/browser/extensions.contribution.ts index b8cd70b08b4d8..e88cccc908174 100644 --- a/src/vs/workbench/contrib/extensions/browser/extensions.contribution.ts +++ b/src/vs/workbench/contrib/extensions/browser/extensions.contribution.ts @@ -19,7 +19,7 @@ import { ExtensionsWorkbenchService } from 'vs/workbench/contrib/extensions/brow import { OpenExtensionsViewletAction, InstallExtensionsAction, ShowOutdatedExtensionsAction, ShowRecommendedExtensionsAction, ShowRecommendedKeymapExtensionsAction, ShowPopularExtensionsAction, ShowEnabledExtensionsAction, ShowInstalledExtensionsAction, ShowDisabledExtensionsAction, ShowBuiltInExtensionsAction, UpdateAllAction, - EnableAllAction, EnableAllWorkspaceAction, DisableAllAction, DisableAllWorkspaceAction, CheckForUpdatesAction, ShowLanguageExtensionsAction, ShowAzureExtensionsAction, EnableAutoUpdateAction, DisableAutoUpdateAction, ConfigureRecommendedExtensionsCommandsContributor, InstallVSIXAction, ReinstallAction, InstallSpecificVersionOfExtensionAction + EnableAllAction, EnableAllWorkspaceAction, DisableAllAction, DisableAllWorkspaceAction, CheckForUpdatesAction, ShowLanguageExtensionsAction, ShowAzureExtensionsAction, EnableAutoUpdateAction, DisableAutoUpdateAction, ConfigureRecommendedExtensionsCommandsContributor, InstallVSIXAction, ReinstallAction, InstallSpecificVersionOfExtensionAction, ClearExtensionsSearchResultsAction } from 'vs/workbench/contrib/extensions/browser/extensionsActions'; import { ExtensionsInput } from 'vs/workbench/contrib/extensions/common/extensionsInput'; import { ExtensionEditor } from 'vs/workbench/contrib/extensions/browser/extensionEditor'; @@ -148,6 +148,7 @@ actionRegistry.registerWorkbenchAction(enableAllWorkspaceAction, 'Extensions: En const checkForUpdatesAction = SyncActionDescriptor.from(CheckForUpdatesAction); actionRegistry.registerWorkbenchAction(checkForUpdatesAction, `Extensions: Check for Extension Updates`, ExtensionsLabel); +actionRegistry.registerWorkbenchAction(SyncActionDescriptor.from(ClearExtensionsSearchResultsAction), 'Extensions: Clear Extensions Search Results', ExtensionsLabel); actionRegistry.registerWorkbenchAction(SyncActionDescriptor.from(EnableAutoUpdateAction), `Extensions: Enable Auto Updating Extensions`, ExtensionsLabel); actionRegistry.registerWorkbenchAction(SyncActionDescriptor.from(DisableAutoUpdateAction), `Extensions: Disable Auto Updating Extensions`, ExtensionsLabel); actionRegistry.registerWorkbenchAction(SyncActionDescriptor.from(InstallSpecificVersionOfExtensionAction), 'Install Specific Version of Extension...', ExtensionsLabel); diff --git a/src/vs/workbench/contrib/extensions/browser/extensionsActions.ts b/src/vs/workbench/contrib/extensions/browser/extensionsActions.ts index 7dc74ead1e35c..06d067ad56140 100644 --- a/src/vs/workbench/contrib/extensions/browser/extensionsActions.ts +++ b/src/vs/workbench/contrib/extensions/browser/extensionsActions.ts @@ -60,6 +60,7 @@ import { IProductService } from 'vs/platform/product/common/productService'; import { IFileDialogService, IDialogService } from 'vs/platform/dialogs/common/dialogs'; import { IProgressService, ProgressLocation } from 'vs/platform/progress/common/progress'; import { Codicon } from 'vs/base/common/codicons'; +import { IViewsService } from 'vs/workbench/common/views'; export function toExtensionDescription(local: ILocalExtension): IExtensionDescription { return { @@ -1641,19 +1642,39 @@ export class ShowDisabledExtensionsAction extends Action { } } -export class ClearExtensionsInputAction extends Action { +export class ClearExtensionsSearchResultsAction extends Action { - static readonly ID = 'workbench.extensions.action.clearExtensionsInput'; - static readonly LABEL = localize('clearExtensionsInput', "Clear Extensions Search Results"); + static readonly ID = 'workbench.extensions.action.clearExtensionsSearchResults'; + static readonly LABEL = localize('clearExtensionsSearchResults', "Clear Extensions Search Results"); + + constructor( + id: string, + label: string, + @IViewsService private readonly viewsService: IViewsService + ) { + super(id, label, 'codicon-clear-all', true); + } + + async run(): Promise { + const viewPaneContainer = this.viewsService.getActiveViewPaneContainerWithId(VIEWLET_ID); + if (viewPaneContainer) { + const extensionsViewPaneContainer = viewPaneContainer as IExtensionsViewPaneContainer; + extensionsViewPaneContainer.search(''); + extensionsViewPaneContainer.focus(); + } + } +} + +export class ClearExtensionsInputAction extends ClearExtensionsSearchResultsAction { constructor( id: string, label: string, onSearchChange: Event, value: string, - @IViewletService private readonly viewletService: IViewletService + @IViewsService viewsService: IViewsService ) { - super(id, label, 'codicon-clear-all', true); + super(id, label, viewsService); this.onSearchChange(value); this._register(onSearchChange(this.onSearchChange, this)); } @@ -1662,14 +1683,6 @@ export class ClearExtensionsInputAction extends Action { this.enabled = !!value; } - run(): Promise { - return this.viewletService.openViewlet(VIEWLET_ID, true) - .then(viewlet => viewlet?.getViewPaneContainer() as IExtensionsViewPaneContainer) - .then(viewlet => { - viewlet.search(''); - viewlet.focus(); - }); - } } export class ShowBuiltInExtensionsAction extends Action { diff --git a/src/vs/workbench/test/browser/workbenchTestServices.ts b/src/vs/workbench/test/browser/workbenchTestServices.ts index 2c449ff0d3f2a..dfc258f39b05d 100644 --- a/src/vs/workbench/test/browser/workbenchTestServices.ts +++ b/src/vs/workbench/test/browser/workbenchTestServices.ts @@ -495,6 +495,7 @@ export class TestViewsService implements IViewsService { openView(id: string, focus?: boolean | undefined): Promise { return Promise.resolve(null); } closeView(id: string): void { } getViewProgressIndicator(id: string) { return null!; } + getActiveViewPaneContainerWithId(id: string) { return null; } } export class TestEditorGroupsService implements IEditorGroupsService { From 7cca5b9e520349b752cd54f86a7f1fbae9d444f0 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Wed, 1 Jul 2020 15:46:06 +0200 Subject: [PATCH 27/93] fix tests --- .../configurationService.test.ts | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) rename src/vs/platform/configuration/test/{node => common}/configurationService.test.ts (93%) diff --git a/src/vs/platform/configuration/test/node/configurationService.test.ts b/src/vs/platform/configuration/test/common/configurationService.test.ts similarity index 93% rename from src/vs/platform/configuration/test/node/configurationService.test.ts rename to src/vs/platform/configuration/test/common/configurationService.test.ts index 2df13d8c9b6a8..2d19fcf1308ae 100644 --- a/src/vs/platform/configuration/test/node/configurationService.test.ts +++ b/src/vs/platform/configuration/test/common/configurationService.test.ts @@ -8,7 +8,6 @@ import * as assert from 'assert'; import { Registry } from 'vs/platform/registry/common/platform'; import { ConfigurationService } from 'vs/platform/configuration/common/configurationService'; import { IConfigurationRegistry, Extensions as ConfigurationExtensions } from 'vs/platform/configuration/common/configurationRegistry'; -import { testFile, ITestFileResult } from 'vs/base/test/node/utils'; import { URI } from 'vs/base/common/uri'; import { ConfigurationTarget } from 'vs/platform/configuration/common/configuration'; import { Event } from 'vs/base/common/event'; @@ -20,27 +19,20 @@ import { IFileService } from 'vs/platform/files/common/files'; import { VSBuffer } from 'vs/base/common/buffer'; import { InMemoryFileSystemProvider } from 'vs/platform/files/common/inMemoryFilesystemProvider'; -suite('ConfigurationService - Node', () => { +suite('ConfigurationService', () => { let fileService: IFileService; - let testFileResult: ITestFileResult; let settingsResource: URI; const disposables: DisposableStore = new DisposableStore(); setup(async () => { - fileService = new FileService(new NullLogService()); - disposables.add(fileService); - const diskFileSystemProvider = new InMemoryFileSystemProvider(); - disposables.add(diskFileSystemProvider); + fileService = disposables.add(new FileService(new NullLogService())); + const diskFileSystemProvider = disposables.add(new InMemoryFileSystemProvider()); fileService.registerProvider(Schemas.file, diskFileSystemProvider); - testFileResult = await testFile('config', 'config.json'); - settingsResource = URI.file(testFileResult.testFile); + settingsResource = URI.file('settings.json'); }); - teardown(async () => { - disposables.clear(); - await testFileResult.cleanUp(); - }); + teardown(() => disposables.clear()); test('simple', async () => { await fileService.writeFile(settingsResource, VSBuffer.fromString('{ "foo": "bar" }')); From 41b98ed0be5f27b8dc12a8c068b6c105a148ee4f Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Wed, 1 Jul 2020 15:50:51 +0200 Subject: [PATCH 28/93] fix https://github.com/microsoft/vscode/issues/100633 --- .../parts/editor/breadcrumbsControl.ts | 14 +++++++++++++- .../browser/parts/editor/breadcrumbsModel.ts | 3 ++- .../parts/editor/breadcrumbModel.test.ts | 19 +++++++++++++++++-- 3 files changed, 32 insertions(+), 4 deletions(-) diff --git a/src/vs/workbench/browser/parts/editor/breadcrumbsControl.ts b/src/vs/workbench/browser/parts/editor/breadcrumbsControl.ts index d69abfe14e988..3a1bd94916823 100644 --- a/src/vs/workbench/browser/parts/editor/breadcrumbsControl.ts +++ b/src/vs/workbench/browser/parts/editor/breadcrumbsControl.ts @@ -38,7 +38,7 @@ import { ResourceLabel } from 'vs/workbench/browser/labels'; import { BreadcrumbsConfig, IBreadcrumbsService } from 'vs/workbench/browser/parts/editor/breadcrumbs'; import { BreadcrumbElement, EditorBreadcrumbsModel, FileElement } from 'vs/workbench/browser/parts/editor/breadcrumbsModel'; import { BreadcrumbsPicker, createBreadcrumbsPicker } from 'vs/workbench/browser/parts/editor/breadcrumbsPicker'; -import { IEditorPartOptions, toResource, SideBySideEditor } from 'vs/workbench/common/editor'; +import { IEditorPartOptions, toResource, SideBySideEditor, SideBySideEditorInput, IEditorInputFactoryRegistry, Extensions } from 'vs/workbench/common/editor'; import { ACTIVE_GROUP, ACTIVE_GROUP_TYPE, IEditorService, SIDE_GROUP, SIDE_GROUP_TYPE } from 'vs/workbench/services/editor/common/editorService'; import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; @@ -49,6 +49,7 @@ import { withNullAsUndefined, withUndefinedAsNull } from 'vs/base/common/types'; import { ILabelService } from 'vs/platform/label/common/label'; import { ITextResourceConfigurationService } from 'vs/editor/common/services/textResourceConfigurationService'; import { TextEditorSelectionRevealType } from 'vs/platform/editor/common/editor'; +import { Registry } from 'vs/platform/registry/common/platform'; class Item extends BreadcrumbsItem { @@ -248,12 +249,23 @@ export class BreadcrumbsControl { } } + // display uri which can be derived from file input + let fileInfoUri = uri; + let input = this._editorGroup.activeEditor; + if (input instanceof SideBySideEditorInput) { + input = input.primary; + } + if (Registry.as(Extensions.EditorInputFactories).getFileEditorInputFactory().isFileEditorInput(input)) { + fileInfoUri = input.label; + } + this.domNode.classList.toggle('hidden', false); this._ckBreadcrumbsVisible.set(true); this._ckBreadcrumbsPossible.set(true); const editor = this._getActiveCodeEditor(); const model = new EditorBreadcrumbsModel( + fileInfoUri, uri, editor, this._configurationService, this._textResourceConfigurationService, diff --git a/src/vs/workbench/browser/parts/editor/breadcrumbsModel.ts b/src/vs/workbench/browser/parts/editor/breadcrumbsModel.ts index 1d7752320b4b2..01ff3916e98a4 100644 --- a/src/vs/workbench/browser/parts/editor/breadcrumbsModel.ts +++ b/src/vs/workbench/browser/parts/editor/breadcrumbsModel.ts @@ -52,6 +52,7 @@ export class EditorBreadcrumbsModel { readonly onDidUpdate: Event = this._onDidUpdate.event; constructor( + fileInfoUri: URI, private readonly _uri: URI, private readonly _editor: ICodeEditor | undefined, @IConfigurationService private readonly _configurationService: IConfigurationService, @@ -64,7 +65,7 @@ export class EditorBreadcrumbsModel { this._disposables.add(this._cfgFilePath.onDidChange(_ => this._onDidUpdate.fire(this))); this._disposables.add(this._cfgSymbolPath.onDidChange(_ => this._onDidUpdate.fire(this))); - this._fileInfo = EditorBreadcrumbsModel._initFilePathInfo(this._uri, workspaceService); + this._fileInfo = EditorBreadcrumbsModel._initFilePathInfo(fileInfoUri, workspaceService); this._bindToEditor(); this._onDidUpdate.fire(this); } diff --git a/src/vs/workbench/test/browser/parts/editor/breadcrumbModel.test.ts b/src/vs/workbench/test/browser/parts/editor/breadcrumbModel.test.ts index 067919112c639..1a39ca039668d 100644 --- a/src/vs/workbench/test/browser/parts/editor/breadcrumbModel.test.ts +++ b/src/vs/workbench/test/browser/parts/editor/breadcrumbModel.test.ts @@ -32,7 +32,7 @@ suite('Breadcrumb Model', function () { test('only uri, inside workspace', function () { - let model = new EditorBreadcrumbsModel(URI.parse('foo:/bar/baz/ws/some/path/file.ts'), undefined, configService, configService, workspaceService); + let model = new EditorBreadcrumbsModel(URI.parse('foo:/bar/baz/ws/some/path/file.ts'), URI.parse('foo:/bar/baz/ws/some/path/file.ts'), undefined, configService, configService, workspaceService); let elements = model.getElements(); assert.equal(elements.length, 3); @@ -45,9 +45,24 @@ suite('Breadcrumb Model', function () { assert.equal(three.uri.toString(), 'foo:/bar/baz/ws/some/path/file.ts'); }); + test('display uri matters for FileElement', function () { + + let model = new EditorBreadcrumbsModel(URI.parse('foo:/bar/baz/ws/some/PATH/file.ts'), URI.parse('foo:/bar/baz/ws/some/path/file.ts'), undefined, configService, configService, workspaceService); + let elements = model.getElements(); + + assert.equal(elements.length, 3); + let [one, two, three] = elements as FileElement[]; + assert.equal(one.kind, FileKind.FOLDER); + assert.equal(two.kind, FileKind.FOLDER); + assert.equal(three.kind, FileKind.FILE); + assert.equal(one.uri.toString(), 'foo:/bar/baz/ws/some'); + assert.equal(two.uri.toString(), 'foo:/bar/baz/ws/some/PATH'); + assert.equal(three.uri.toString(), 'foo:/bar/baz/ws/some/PATH/file.ts'); + }); + test('only uri, outside workspace', function () { - let model = new EditorBreadcrumbsModel(URI.parse('foo:/outside/file.ts'), undefined, configService, configService, workspaceService); + let model = new EditorBreadcrumbsModel(URI.parse('foo:/outside/file.ts'), URI.parse('foo:/outside/file.ts'), undefined, configService, configService, workspaceService); let elements = model.getElements(); assert.equal(elements.length, 2); From 71b845cca22a09cbb6549f14dc38fb982ab08cf1 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Wed, 1 Jul 2020 06:52:54 -0700 Subject: [PATCH 29/93] Shell path -> shell executable Fixes #101482 --- src/vs/workbench/contrib/terminal/node/terminalProcess.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/contrib/terminal/node/terminalProcess.ts b/src/vs/workbench/contrib/terminal/node/terminalProcess.ts index 481754cbd829a..36838ff5050c4 100644 --- a/src/vs/workbench/contrib/terminal/node/terminalProcess.ts +++ b/src/vs/workbench/contrib/terminal/node/terminalProcess.ts @@ -111,7 +111,7 @@ export class TerminalProcess extends Disposable implements ITerminalChildProcess try { const result = await stat(slc.executable); if (!result.isFile() && !result.isSymbolicLink()) { - return { message: localize('launchFail.executableIsNotFileOrSymlink', "Shell path \"{0}\" is not a file of a symlink", slc.executable) }; + return { message: localize('launchFail.executableIsNotFileOrSymlink', "Path to shell executable \"{0}\" is not a file of a symlink", slc.executable) }; } } catch (err) { if (err?.code === 'ENOENT') { @@ -120,7 +120,7 @@ export class TerminalProcess extends Disposable implements ITerminalChildProcess const envPaths: string[] | undefined = (slc.env && slc.env.PATH) ? slc.env.PATH.split(path.delimiter) : undefined; const executable = await findExecutable(slc.executable!, cwd, envPaths); if (!executable) { - return { message: localize('launchFail.executableDoesNotExist', "Shell path \"{0}\" does not exist", slc.executable) }; + return { message: localize('launchFail.executableDoesNotExist', "Path to shell executable \"{0}\" does not exist", slc.executable) }; } } } From fb2d4b9bfe16aa682ce97d9a7fa21dff5e6805a5 Mon Sep 17 00:00:00 2001 From: isidor Date: Wed, 1 Jul 2020 15:58:54 +0200 Subject: [PATCH 30/93] fixes #101400 --- src/vs/workbench/contrib/debug/browser/debugService.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/contrib/debug/browser/debugService.ts b/src/vs/workbench/contrib/debug/browser/debugService.ts index b94c4b4897d45..71cab8c94c1df 100644 --- a/src/vs/workbench/contrib/debug/browser/debugService.ts +++ b/src/vs/workbench/contrib/debug/browser/debugService.ts @@ -348,8 +348,8 @@ export class DebugService implements IDebugService { } if (configOrName && !config) { - const message = !!launch ? nls.localize('configMissing', "Configuration '{0}' is missing in 'launch.json'.", typeof configOrName === 'string' ? configOrName : JSON.stringify(configOrName)) : - nls.localize('launchJsonDoesNotExist', "'launch.json' does not exist."); + const message = !!launch ? nls.localize('configMissing', "Configuration '{0}' is missing in 'launch.json'.", typeof configOrName === 'string' ? configOrName : configOrName.name) : + nls.localize('launchJsonDoesNotExist', "'launch.json' does not exist for passed workspace folder."); throw new Error(message); } @@ -358,6 +358,7 @@ export class DebugService implements IDebugService { return result; } catch (err) { // make sure to get out of initializing state, and propagate the result + this.notificationService.error(err); this.endInitializingState(); return Promise.reject(err); } From 0edc0c185b59ed8fe26525a23228cead22d6cd1a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Wed, 1 Jul 2020 16:07:50 +0200 Subject: [PATCH 31/93] fixes #101094 --- src/vs/workbench/contrib/scm/browser/scmViewPane.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/vs/workbench/contrib/scm/browser/scmViewPane.ts b/src/vs/workbench/contrib/scm/browser/scmViewPane.ts index a5e07cfdfbd52..7fc87021805da 100644 --- a/src/vs/workbench/contrib/scm/browser/scmViewPane.ts +++ b/src/vs/workbench/contrib/scm/browser/scmViewPane.ts @@ -724,20 +724,20 @@ class SCMResourceIdentityProvider implements IIdentityProvider { getId(element: TreeElement): string { if (ResourceTree.isResourceNode(element)) { const group = element.context; - return `folder:${group.provider.contextValue}/${group.id}/$FOLDER/${element.uri.toString()}`; + return `folder:${group.provider.id}/${group.id}/$FOLDER/${element.uri.toString()}`; } else if (isSCMRepository(element)) { const provider = element.provider; - return `repo:${provider.contextValue}`; + return `repo:${provider.id}`; } else if (isSCMInput(element)) { const provider = element.repository.provider; - return `input:${provider.contextValue}`; + return `input:${provider.id}`; } else if (isSCMResource(element)) { const group = element.resourceGroup; const provider = group.provider; - return `resource:${provider.contextValue}/${group.id}/${element.sourceUri.toString()}`; + return `resource:${provider.id}/${group.id}/${element.sourceUri.toString()}`; } else { const provider = element.provider; - return `group:${provider.contextValue}/${element.id}`; + return `group:${provider.id}/${element.id}`; } } } From c87bc472b8e240884608422a931011e821e81538 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Wed, 1 Jul 2020 16:09:46 +0200 Subject: [PATCH 32/93] fixes #101103 --- .../contrib/scm/browser/scmViewPane.ts | 20 ++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/src/vs/workbench/contrib/scm/browser/scmViewPane.ts b/src/vs/workbench/contrib/scm/browser/scmViewPane.ts index 7fc87021805da..624922ae34d99 100644 --- a/src/vs/workbench/contrib/scm/browser/scmViewPane.ts +++ b/src/vs/workbench/contrib/scm/browser/scmViewPane.ts @@ -6,7 +6,7 @@ import 'vs/css!./media/scm'; import { Event, Emitter } from 'vs/base/common/event'; import { basename, dirname, isEqual } from 'vs/base/common/resources'; -import { IDisposable, Disposable, DisposableStore, combinedDisposable } from 'vs/base/common/lifecycle'; +import { IDisposable, Disposable, DisposableStore, combinedDisposable, toDisposable } from 'vs/base/common/lifecycle'; import { ViewPane, IViewPaneOptions } from 'vs/workbench/browser/parts/views/viewPaneContainer'; import { append, $, addClass, toggleClass, removeClass, Dimension } from 'vs/base/browser/dom'; import { IListVirtualDelegate, IIdentityProvider } from 'vs/base/browser/ui/list/list'; @@ -59,7 +59,7 @@ import { SelectionClipboardContributionID } from 'vs/workbench/contrib/codeEdito import { ContextMenuController } from 'vs/editor/contrib/contextmenu/contextmenu'; import * as platform from 'vs/base/common/platform'; import { escape, compare, format } from 'vs/base/common/strings'; -import { inputPlaceholderForeground, inputValidationInfoBorder, inputValidationWarningBorder, inputValidationErrorBorder, inputValidationInfoBackground, inputValidationInfoForeground, inputValidationWarningBackground, inputValidationWarningForeground, inputValidationErrorBackground, inputValidationErrorForeground, inputBackground, inputForeground, inputBorder, focusBorder } from 'vs/platform/theme/common/colorRegistry'; +import { inputPlaceholderForeground, inputValidationInfoBorder, inputValidationWarningBorder, inputValidationErrorBorder, inputValidationInfoBackground, inputValidationInfoForeground, inputValidationWarningBackground, inputValidationWarningForeground, inputValidationErrorBackground, inputValidationErrorForeground, inputBackground, inputForeground, inputBorder, focusBorder, registerColor, contrastBorder } from 'vs/platform/theme/common/colorRegistry'; import { SuggestController } from 'vs/editor/contrib/suggest/suggestController'; import { SnippetController2 } from 'vs/editor/contrib/snippet/snippetController2'; import { Schemas } from 'vs/base/common/network'; @@ -174,7 +174,10 @@ class RepositoryRenderer implements ICompressibleTreeRenderer removeClass(row, 'scm-provider-row')); const provider = append(container, $('.scm-provider')); const label = append(provider, $('.label')); @@ -188,7 +191,7 @@ class RepositoryRenderer implements ICompressibleTreeRenderer toggleClass(provider, 'active', e)); const disposable = Disposable.None; - const templateDisposable = combinedDisposable(visibilityDisposable, toolBar, badgeStyler); + const templateDisposable = combinedDisposable(rowDisposable, visibilityDisposable, toolBar, badgeStyler); return { name, description, countContainer, count, toolBar, disposable, templateDisposable }; } @@ -985,7 +988,7 @@ class ViewModel { children.push(...item.groupItems.map(i => this.render(i))); } - return { element: item.element, children, incompressible: true, collapsible: true }; + return { element: item.element, children, incompressible: true, collapsible: hasSomeChanges }; } else { const children = this.mode === ViewModelMode.List ? Iterable.map(item.resources, element => ({ element, incompressible: true })) @@ -1772,6 +1775,8 @@ export class SCMViewPane extends ViewPane { } } +export const scmProviderSeparatorBorderColor = registerColor('scm.providerBorder', { dark: '#454545', light: '#C8C8C8', hc: contrastBorder }, localize('scm.providerBorder', "SCM Provider separator border.")); + registerThemingParticipant((theme, collector) => { const inputBackgroundColor = theme.getColor(inputBackground); if (inputBackgroundColor) { @@ -1858,4 +1863,9 @@ registerThemingParticipant((theme, collector) => { if (repositoryStatusActionsBorderColor) { collector.addRule(`.scm-view .scm-provider > .status > .monaco-action-bar > .actions-container { border-color: ${repositoryStatusActionsBorderColor}; }`); } + + const providerSeparatorBorderColor = theme.getColor(scmProviderSeparatorBorderColor); + if (providerSeparatorBorderColor) { + collector.addRule(`.scm-view .scm-provider-row:not([data-index="0"]) { border-top: 1px dashed ${providerSeparatorBorderColor}; }`); + } }); From 96f2799b864f6d2057ac3baa74d42efaecff79b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Wed, 1 Jul 2020 16:17:12 +0200 Subject: [PATCH 33/93] fixes #101410 --- .../workbench/contrib/scm/browser/media/scm.css | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/vs/workbench/contrib/scm/browser/media/scm.css b/src/vs/workbench/contrib/scm/browser/media/scm.css index 61dc3b4fecfbf..78e34e1f8e78e 100644 --- a/src/vs/workbench/contrib/scm/browser/media/scm.css +++ b/src/vs/workbench/contrib/scm/browser/media/scm.css @@ -52,14 +52,19 @@ justify-content: flex-end; } -.scm-view .scm-provider > .actions .monaco-action-bar .action-item { +/** + * The following rules are very specific because of inline drop down menus + * https://github.com/microsoft/vscode/issues/101410 + */ +.scm-view .scm-provider > .actions > .monaco-toolbar > .monaco-action-bar > .actions-container > .action-item { padding-left: 4px; display: flex; align-items: center; min-width: 16px; } -.scm-view .scm-provider > .actions .monaco-action-bar .action-label { +.scm-view .scm-provider > .actions > .monaco-toolbar > .monaco-action-bar > .actions-container > .action-item > .action-label, +.scm-view .scm-provider > .actions > .monaco-toolbar > .monaco-action-bar > .actions-container > .action-item > .monaco-dropdown > .dropdown-label > .action-label { display: flex; align-items: center; overflow: hidden; @@ -68,12 +73,7 @@ margin: 0; } -.scm-view .scm-provider > .actions .monaco-action-bar .action-label .codicon { - vertical-align: sub; - display: inline-flex; -} - -.scm-view .scm-provider > .actions .monaco-action-bar .action-item:last-of-type { +.scm-view .scm-provider > .actions > .monaco-toolbar > .monaco-action-bar > .actions-container > .action-item:last-of-type { padding-right: 0; } From 9d66cd6fda8bad2a5c0f91e66c97657ff7a4c134 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Wed, 1 Jul 2020 16:17:36 +0200 Subject: [PATCH 34/93] fix #98920 --- .../contrib/extensions/browser/extensionEditor.ts | 12 ++++++------ .../extensions/browser/media/extensionEditor.css | 7 +++---- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/src/vs/workbench/contrib/extensions/browser/extensionEditor.ts b/src/vs/workbench/contrib/extensions/browser/extensionEditor.ts index 4a4090f4c942a..1e72361f58f00 100644 --- a/src/vs/workbench/contrib/extensions/browser/extensionEditor.ts +++ b/src/vs/workbench/contrib/extensions/browser/extensionEditor.ts @@ -224,23 +224,23 @@ export class ExtensionEditor extends BaseEditor { builtin.textContent = localize('builtin', "Built-in"); const subtitle = append(details, $('.subtitle')); - const publisher = append(subtitle, $('span.publisher.clickable', { title: localize('publisher', "Publisher name"), tabIndex: 0 })); + const publisher = append(append(subtitle, $('.subtitle-entry')), $('span.publisher.clickable', { title: localize('publisher', "Publisher name"), tabIndex: 0 })); - const installCount = append(subtitle, $('span.install', { title: localize('install count', "Install count"), tabIndex: 0 })); + const installCount = append(append(subtitle, $('.subtitle-entry')), $('span.install', { title: localize('install count', "Install count"), tabIndex: 0 })); - const rating = append(subtitle, $('span.rating.clickable', { title: localize('rating', "Rating"), tabIndex: 0 })); + const rating = append(append(subtitle, $('.subtitle-entry')), $('span.rating.clickable', { title: localize('rating', "Rating"), tabIndex: 0 })); - const repository = append(subtitle, $('span.repository.clickable')); + const repository = append(append(subtitle, $('.subtitle-entry')), $('span.repository.clickable')); repository.textContent = localize('repository', 'Repository'); repository.style.display = 'none'; repository.tabIndex = 0; - const license = append(subtitle, $('span.license.clickable')); + const license = append(append(subtitle, $('.subtitle-entry')), $('span.license.clickable')); license.textContent = localize('license', 'License'); license.style.display = 'none'; license.tabIndex = 0; - const version = append(subtitle, $('span.version')); + const version = append(append(subtitle, $('.subtitle-entry')), $('span.version')); version.textContent = localize('version', 'Version'); const description = append(details, $('.description')); diff --git a/src/vs/workbench/contrib/extensions/browser/media/extensionEditor.css b/src/vs/workbench/contrib/extensions/browser/media/extensionEditor.css index a6293c6dda0fd..3270a34f18ed8 100644 --- a/src/vs/workbench/contrib/extensions/browser/media/extensionEditor.css +++ b/src/vs/workbench/contrib/extensions/browser/media/extensionEditor.css @@ -113,7 +113,7 @@ line-height: 20px; } -.extension-editor > .header > .details > .subtitle > .publisher { +.extension-editor > .header > .details > .subtitle .publisher { font-size: 18px; } @@ -124,12 +124,11 @@ align-items: center; } -.extension-editor > .header > .details > .subtitle > .install > .count { +.extension-editor > .header > .details > .subtitle .install > .count { margin-left: 6px; } -.extension-editor > .header > .details > .subtitle > span:not(:first-child):not(:empty), -.extension-editor > .header > .details > .subtitle > a:not(:first-child):not(:empty) { +.extension-editor > .header > .details > .subtitle > div:not(:first-child):not(:empty) { border-left: 1px solid rgba(128, 128, 128, 0.7); margin-left: 14px; padding-left: 14px; From 4893dbd53d7d0ef0f7d992a59277f61b581095c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Wed, 1 Jul 2020 16:26:10 +0200 Subject: [PATCH 35/93] fixes #101146 --- src/vs/workbench/contrib/scm/browser/scmViewPane.ts | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/scm/browser/scmViewPane.ts b/src/vs/workbench/contrib/scm/browser/scmViewPane.ts index 624922ae34d99..93ca0473d3d31 100644 --- a/src/vs/workbench/contrib/scm/browser/scmViewPane.ts +++ b/src/vs/workbench/contrib/scm/browser/scmViewPane.ts @@ -855,6 +855,7 @@ class ViewModel { private visibilityDisposables = new DisposableStore(); private scrollTop: number | undefined; private firstVisible = true; + private repositoryCollapseStates: Map | undefined; private disposables = new DisposableStore(); constructor( @@ -950,6 +951,7 @@ class ViewModel { this.visibilityDisposables = new DisposableStore(); this.repositories.onDidSplice(this.onDidSpliceRepositories, this, this.visibilityDisposables); this.onDidSpliceRepositories({ start: 0, deleteCount: 0, toInsert: this.repositories.elements }); + this.repositoryCollapseStates = undefined; if (typeof this.scrollTop === 'number') { this.tree.scrollTop = this.scrollTop; @@ -959,6 +961,14 @@ class ViewModel { this.editorService.onDidActiveEditorChange(this.onDidActiveEditorChange, this, this.visibilityDisposables); this.onDidActiveEditorChange(); } else { + if (this.items.length > 1) { + this.repositoryCollapseStates = new Map(); + + for (const item of this.items) { + this.repositoryCollapseStates.set(item.element, this.tree.isCollapsed(item.element)); + } + } + this.visibilityDisposables.dispose(); this.onDidSpliceRepositories({ start: 0, deleteCount: this.items.length, toInsert: [] }); this.scrollTop = this.tree.scrollTop; @@ -988,7 +998,8 @@ class ViewModel { children.push(...item.groupItems.map(i => this.render(i))); } - return { element: item.element, children, incompressible: true, collapsible: hasSomeChanges }; + const collapsed = this.repositoryCollapseStates?.get(item.element) ?? false; + return { element: item.element, children, incompressible: true, collapsed, collapsible: hasSomeChanges }; } else { const children = this.mode === ViewModelMode.List ? Iterable.map(item.resources, element => ({ element, incompressible: true })) From e80069d600789924f4c724836ff95b2c93f5316e Mon Sep 17 00:00:00 2001 From: Alex Ross Date: Wed, 1 Jul 2020 16:35:36 +0200 Subject: [PATCH 36/93] Reuse hover options in custom tree view Fixes #101495 --- src/vs/workbench/contrib/views/browser/treeView.ts | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/contrib/views/browser/treeView.ts b/src/vs/workbench/contrib/views/browser/treeView.ts index a9626ba711c27..10e0efdbfa14a 100644 --- a/src/vs/workbench/contrib/views/browser/treeView.ts +++ b/src/vs/workbench/contrib/views/browser/treeView.ts @@ -38,7 +38,7 @@ import { FuzzyScore, createMatches } from 'vs/base/common/filters'; import { CollapseAllAction } from 'vs/base/browser/ui/tree/treeDefaults'; import { isFalsyOrWhitespace } from 'vs/base/common/strings'; import { SIDE_BAR_BACKGROUND, PANEL_BACKGROUND } from 'vs/workbench/common/theme'; -import { IHoverService } from 'vs/workbench/services/hover/browser/hover'; +import { IHoverService, IHoverOptions } from 'vs/workbench/services/hover/browser/hover'; class Root implements ITreeItem { label = { label: 'root' }; @@ -795,6 +795,7 @@ class TreeRenderer extends Disposable implements ITreeRenderer Date: Wed, 1 Jul 2020 16:39:54 +0200 Subject: [PATCH 37/93] Fixes #101490: Do not ship standalone editor resources --- build/gulpfile.vscode.js | 1 + 1 file changed, 1 insertion(+) diff --git a/build/gulpfile.vscode.js b/build/gulpfile.vscode.js index 9aa6aff5ea78f..4b46a5d856cb6 100644 --- a/build/gulpfile.vscode.js +++ b/build/gulpfile.vscode.js @@ -64,6 +64,7 @@ const vscodeResources = [ 'out-build/paths.js', 'out-build/vs/**/*.{svg,png,html}', '!out-build/vs/code/browser/**/*.html', + '!out-build/vs/editor/standalone/**/*.svg', 'out-build/vs/base/common/performance.js', 'out-build/vs/base/node/languagePacks.js', 'out-build/vs/base/node/{stdForkStart.js,terminateProcess.sh,cpuUsage.sh,ps.sh}', From f813a020220c3ef98f44fd9604ce113b6e55034f Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Wed, 1 Jul 2020 16:40:26 +0200 Subject: [PATCH 38/93] Fix #100200 --- .../keybinding/common/keybindingEditing.ts | 28 +++++++++++++++++-- .../keybindingEditing.test.ts | 10 +++++++ 2 files changed, 36 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/services/keybinding/common/keybindingEditing.ts b/src/vs/workbench/services/keybinding/common/keybindingEditing.ts index 3b789cbce4e25..e6621b9d06b7c 100644 --- a/src/vs/workbench/services/keybinding/common/keybindingEditing.ts +++ b/src/vs/workbench/services/keybinding/common/keybindingEditing.ts @@ -6,6 +6,7 @@ import { localize } from 'vs/nls'; import { Queue } from 'vs/base/common/async'; import * as json from 'vs/base/common/json'; +import * as objects from 'vs/base/common/objects'; import { setProperty } from 'vs/base/common/jsonEdit'; import { Edit } from 'vs/base/common/jsonFormatter'; import { Disposable, IReference } from 'vs/base/common/lifecycle'; @@ -143,7 +144,11 @@ export class KeybindingsEditingService extends Disposable implements IKeybinding const eol = model.getEOL(); const key = keybindingItem.resolvedKeybinding ? keybindingItem.resolvedKeybinding.getUserSettingsLabel() : null; if (key) { - this.applyEditsToBuffer(setProperty(model.getValue(), [-1], this.asObject(key, keybindingItem.command, keybindingItem.when ? keybindingItem.when.serialize() : undefined, true), { tabSize, insertSpaces, eol })[0], model); + const entry: IUserFriendlyKeybinding = this.asObject(key, keybindingItem.command, keybindingItem.when ? keybindingItem.when.serialize() : undefined, true); + const userKeybindingEntries = json.parse(model.getValue()); + if (userKeybindingEntries.every(e => !this.areSame(e, entry))) { + this.applyEditsToBuffer(setProperty(model.getValue(), [-1], entry, { tabSize, insertSpaces, eol })[0], model); + } } } @@ -196,6 +201,26 @@ export class KeybindingsEditingService extends Disposable implements IKeybinding return object; } + private areSame(a: IUserFriendlyKeybinding, b: IUserFriendlyKeybinding): boolean { + if (a.command !== b.command) { + return false; + } + if (a.key !== b.key) { + return false; + } + const whenA = ContextKeyExpr.deserialize(a.when); + const whenB = ContextKeyExpr.deserialize(b.when); + if ((whenA && !whenB) || (!whenA && whenB)) { + return false; + } + if (whenA && whenB && !whenA.equals(whenB)) { + return false; + } + if (!objects.equals(a.args, b.args)) { + return false; + } + return true; + } private applyEditsToBuffer(edit: Edit, model: ITextModel): void { const startPosition = model.getPositionAt(edit.offset); @@ -206,7 +231,6 @@ export class KeybindingsEditingService extends Disposable implements IKeybinding model.pushEditOperations([new Selection(startPosition.lineNumber, startPosition.column, startPosition.lineNumber, startPosition.column)], [editOperation], () => []); } - private resolveModelReference(): Promise> { return this.fileService.exists(this.resource) .then(exists => { diff --git a/src/vs/workbench/services/keybinding/test/electron-browser/keybindingEditing.test.ts b/src/vs/workbench/services/keybinding/test/electron-browser/keybindingEditing.test.ts index 0fd8abac93b5e..cd493c726b695 100644 --- a/src/vs/workbench/services/keybinding/test/electron-browser/keybindingEditing.test.ts +++ b/src/vs/workbench/services/keybinding/test/electron-browser/keybindingEditing.test.ts @@ -220,6 +220,16 @@ suite('KeybindingsEditing', () => { .then(() => assert.deepEqual(getUserKeybindings(), expected)); }); + test('remove a default keybinding should not ad duplicate entries', async () => { + const expected: IUserFriendlyKeybinding[] = [{ key: 'alt+c', command: '-a' }]; + await testObject.removeKeybinding(aResolvedKeybindingItem({ command: 'a', firstPart: { keyCode: KeyCode.KEY_C, modifiers: { altKey: true } } })); + await testObject.removeKeybinding(aResolvedKeybindingItem({ command: 'a', firstPart: { keyCode: KeyCode.KEY_C, modifiers: { altKey: true } } })); + await testObject.removeKeybinding(aResolvedKeybindingItem({ command: 'a', firstPart: { keyCode: KeyCode.KEY_C, modifiers: { altKey: true } } })); + await testObject.removeKeybinding(aResolvedKeybindingItem({ command: 'a', firstPart: { keyCode: KeyCode.KEY_C, modifiers: { altKey: true } } })); + await testObject.removeKeybinding(aResolvedKeybindingItem({ command: 'a', firstPart: { keyCode: KeyCode.KEY_C, modifiers: { altKey: true } } })); + assert.deepEqual(getUserKeybindings(), expected); + }); + test('remove a user keybinding', () => { writeToKeybindingsFile({ key: 'alt+c', command: 'b' }); return testObject.removeKeybinding(aResolvedKeybindingItem({ command: 'b', firstPart: { keyCode: KeyCode.KEY_C, modifiers: { altKey: true } }, isDefault: false })) From faf9bda06a51afbc5348be3342d514d4dc304df0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Wed, 1 Jul 2020 16:47:43 +0200 Subject: [PATCH 39/93] fixes #101411 --- .../contrib/scm/browser/scmViewPane.ts | 28 ++++++++++--------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/src/vs/workbench/contrib/scm/browser/scmViewPane.ts b/src/vs/workbench/contrib/scm/browser/scmViewPane.ts index 93ca0473d3d31..df056df39217b 100644 --- a/src/vs/workbench/contrib/scm/browser/scmViewPane.ts +++ b/src/vs/workbench/contrib/scm/browser/scmViewPane.ts @@ -304,22 +304,24 @@ class InputRenderer implements ICompressibleTreeRenderer { - this.updateHeight(input, contentHeight + 10); - templateData.inputWidget.layout(); - }); - disposables.add({ dispose: () => clearTimeout(timeout) }); - } + this.updateHeight(input, contentHeight + 10); + templateData.inputWidget.layout(); } }; - disposables.add(templateData.inputWidget.onDidChangeContentHeight(onDidChangeContentHeight)); - onDidChangeContentHeight(); + const initialRender = () => { + disposables.add(templateData.inputWidget.onDidChangeContentHeight(onDidChangeContentHeight)); + onDidChangeContentHeight(); + }; + + const contentHeight = templateData.inputWidget.getContentHeight(); + + if (contentHeight !== InputRenderer.DEFAULT_HEIGHT) { + const timeout = setTimeout(initialRender, 0); + disposables.add({ dispose: () => clearTimeout(timeout) }); + } else { + initialRender(); + } // Layout the editor whenever the outer layout happens const layoutEditor = () => templateData.inputWidget.layout(); From ba4aa7a6131b1e381b3c3a48cd3c3ffd772d5f84 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Wed, 1 Jul 2020 16:56:31 +0200 Subject: [PATCH 40/93] fixes #101432 --- src/vs/workbench/contrib/scm/browser/scmViewPane.ts | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/contrib/scm/browser/scmViewPane.ts b/src/vs/workbench/contrib/scm/browser/scmViewPane.ts index df056df39217b..0925d7059e90a 100644 --- a/src/vs/workbench/contrib/scm/browser/scmViewPane.ts +++ b/src/vs/workbench/contrib/scm/browser/scmViewPane.ts @@ -79,6 +79,8 @@ import { Command } from 'vs/editor/common/modes'; import { renderCodicons } from 'vs/base/common/codicons'; import { ToolBar } from 'vs/base/browser/ui/toolbar/toolbar'; import { AnchorAlignment } from 'vs/base/browser/ui/contextview/contextview'; +import { domEvent } from 'vs/base/browser/event'; +import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent'; type TreeElement = ISCMRepository | ISCMInput | ISCMResourceGroup | IResourceNode | ISCMResource; @@ -272,6 +274,7 @@ class InputRenderer implements ICompressibleTreeRenderer void, + private focusTree: () => void, @IInstantiationService private instantiationService: IInstantiationService, ) { } @@ -279,10 +282,16 @@ class InputRenderer implements ICompressibleTreeRenderer new StandardKeyboardEvent(e)); + const onEscape = Event.filter(onKeyDown, e => e.keyCode === KeyCode.Escape); + disposables.add(onEscape(this.focusTree)); - return { inputWidget, disposable: Disposable.None, templateDisposable: inputWidget }; + return { inputWidget, disposable: Disposable.None, templateDisposable: disposables }; } renderElement(node: ITreeNode, index: number, templateData: InputTemplate): void { @@ -1541,7 +1550,7 @@ export class SCMViewPane extends ViewPane { this._register(repositories.onDidSplice(() => this.updateActions())); - this.inputRenderer = this.instantiationService.createInstance(InputRenderer, this.layoutCache, (input, height) => this.tree.updateElementHeight(input, height)); + this.inputRenderer = this.instantiationService.createInstance(InputRenderer, this.layoutCache, (input, height) => this.tree.updateElementHeight(input, height), () => this.tree.domFocus()); const delegate = new ProviderListDelegate(this.inputRenderer); const actionViewItemProvider = (action: IAction) => this.getActionViewItem(action); From 665bc2c1c3dfb0dd9dbd343f0329154f2d687e73 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Wed, 1 Jul 2020 17:02:18 +0200 Subject: [PATCH 41/93] fixes #101337 --- src/vs/workbench/contrib/scm/browser/media/scm.css | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/vs/workbench/contrib/scm/browser/media/scm.css b/src/vs/workbench/contrib/scm/browser/media/scm.css index 78e34e1f8e78e..e2ae17bfd60de 100644 --- a/src/vs/workbench/contrib/scm/browser/media/scm.css +++ b/src/vs/workbench/contrib/scm/browser/media/scm.css @@ -71,6 +71,8 @@ min-width: 16px; /* for flex */ height: 100%; margin: 0; + background-repeat: no-repeat; + background-position: center; } .scm-view .scm-provider > .actions > .monaco-toolbar > .monaco-action-bar > .actions-container > .action-item:last-of-type { From 37ca38a4fbada14761595cc2a641b8dabe8b2fc0 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Wed, 1 Jul 2020 08:03:09 -0700 Subject: [PATCH 42/93] Add note about re-using options objects Fixes #101495 --- src/vs/workbench/services/hover/browser/hover.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/services/hover/browser/hover.ts b/src/vs/workbench/services/hover/browser/hover.ts index 1602396e2dd91..a504b379d65cd 100644 --- a/src/vs/workbench/services/hover/browser/hover.ts +++ b/src/vs/workbench/services/hover/browser/hover.ts @@ -16,7 +16,7 @@ export interface IHoverService { readonly _serviceBrand: undefined; /** - * Shows a hover. + * Shows a hover, provided a hover with the same options object is not already visible. * @param options A set of options defining the characteristics of the hover. * @param focus Whether to focus the hover (useful for keyboard accessibility). * From 1f31957f810e2507b271de2111e5ba79cc391ca0 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Wed, 1 Jul 2020 17:53:00 +0200 Subject: [PATCH 43/93] contextmenu - do not send functions over ipc (fix #100982) --- src/vs/base/parts/contextmenu/common/contextmenu.ts | 3 +-- .../base/parts/contextmenu/electron-sandbox/contextmenu.ts | 6 +++--- .../contextmenu/electron-sandbox/contextmenuService.ts | 3 +-- 3 files changed, 5 insertions(+), 7 deletions(-) diff --git a/src/vs/base/parts/contextmenu/common/contextmenu.ts b/src/vs/base/parts/contextmenu/common/contextmenu.ts index c31a49474f122..0b99dbcb3280a 100644 --- a/src/vs/base/parts/contextmenu/common/contextmenu.ts +++ b/src/vs/base/parts/contextmenu/common/contextmenu.ts @@ -36,8 +36,7 @@ export interface IPopupOptions { x?: number; y?: number; positioningItem?: number; - onHide?: () => void; } export const CONTEXT_MENU_CHANNEL = 'vscode:contextmenu'; -export const CONTEXT_MENU_CLOSE_CHANNEL = 'vscode:onCloseContextMenu'; \ No newline at end of file +export const CONTEXT_MENU_CLOSE_CHANNEL = 'vscode:onCloseContextMenu'; diff --git a/src/vs/base/parts/contextmenu/electron-sandbox/contextmenu.ts b/src/vs/base/parts/contextmenu/electron-sandbox/contextmenu.ts index 4b5c3fbdf7518..4b8917c342631 100644 --- a/src/vs/base/parts/contextmenu/electron-sandbox/contextmenu.ts +++ b/src/vs/base/parts/contextmenu/electron-sandbox/contextmenu.ts @@ -8,7 +8,7 @@ import { IContextMenuItem, ISerializableContextMenuItem, CONTEXT_MENU_CLOSE_CHAN let contextMenuIdPool = 0; -export function popup(items: IContextMenuItem[], options?: IPopupOptions): void { +export function popup(items: IContextMenuItem[], options?: IPopupOptions, onHide?: () => void): void { const processedItems: IContextMenuItem[] = []; const contextMenuId = contextMenuIdPool++; @@ -28,8 +28,8 @@ export function popup(items: IContextMenuItem[], options?: IPopupOptions): void ipcRenderer.removeListener(onClickChannel, onClickChannelHandler); - if (options?.onHide) { - options.onHide(); + if (onHide) { + onHide(); } }); diff --git a/src/vs/workbench/services/contextmenu/electron-sandbox/contextmenuService.ts b/src/vs/workbench/services/contextmenu/electron-sandbox/contextmenuService.ts index 18bd53217cd31..51e33eff6cb1d 100644 --- a/src/vs/workbench/services/contextmenu/electron-sandbox/contextmenuService.ts +++ b/src/vs/workbench/services/contextmenu/electron-sandbox/contextmenuService.ts @@ -118,8 +118,7 @@ class NativeContextMenuService extends Disposable implements IContextMenuService x: Math.floor(x), y: Math.floor(y), positioningItem: delegate.autoSelectFirstItem ? 0 : undefined, - onHide: () => onHide() - }); + }, () => onHide()); } } From 0fe3b64da887b7984242dc59b50969bef3df40b0 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Wed, 1 Jul 2020 09:02:25 -0700 Subject: [PATCH 44/93] Add warning about async usage of provideTerminalLinks Fixes #101458 --- src/vs/vscode.proposed.d.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/vs/vscode.proposed.d.ts b/src/vs/vscode.proposed.d.ts index 4196af4833c99..40c73e63abcd4 100644 --- a/src/vs/vscode.proposed.d.ts +++ b/src/vs/vscode.proposed.d.ts @@ -1052,7 +1052,9 @@ declare module 'vscode' { export interface TerminalLinkProvider { /** - * Provide terminal links for the given context. + * Provide terminal links for the given context. Note that this can be called multiple times + * even before previous calls resolve, make sure to not share global objects (eg. `RegExp`) + * that could have problems when asynchronous usage may overlap. * @param context Information about what links are being provided for. */ provideTerminalLinks(context: TerminalLinkContext): ProviderResult From 06b9d1850f21c5abcc5c414a9295414fb39d8647 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Wed, 1 Jul 2020 09:07:42 -0700 Subject: [PATCH 45/93] Don't call ext link provider for empty lines Fixes #101452 --- .../browser/links/terminalExternalLinkProviderAdapter.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/vs/workbench/contrib/terminal/browser/links/terminalExternalLinkProviderAdapter.ts b/src/vs/workbench/contrib/terminal/browser/links/terminalExternalLinkProviderAdapter.ts index aa8f0f670af3b..40478f7f7f991 100644 --- a/src/vs/workbench/contrib/terminal/browser/links/terminalExternalLinkProviderAdapter.ts +++ b/src/vs/workbench/contrib/terminal/browser/links/terminalExternalLinkProviderAdapter.ts @@ -47,6 +47,10 @@ export class TerminalExternalLinkProviderAdapter extends TerminalBaseLinkProvide } const lineContent = getXtermLineContent(this._xterm.buffer.active, startLine, endLine, this._xterm.cols); + if (lineContent.trim().length === 0) { + return []; + } + const externalLinks = await this._externalLinkProvider.provideLinks(this._instance, lineContent); if (!externalLinks) { return []; From 0bd3862a44361d4dafa587368c1761495b62d3c3 Mon Sep 17 00:00:00 2001 From: Miguel Solorio Date: Wed, 1 Jul 2020 10:45:46 -0700 Subject: [PATCH 46/93] Add border to top and bottom focused notebook cells (refs #101375) --- .../notebook/browser/media/notebook.css | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/src/vs/workbench/contrib/notebook/browser/media/notebook.css b/src/vs/workbench/contrib/notebook/browser/media/notebook.css index 067140864ca58..ddcf1ae2d0434 100644 --- a/src/vs/workbench/contrib/notebook/browser/media/notebook.css +++ b/src/vs/workbench/contrib/notebook/browser/media/notebook.css @@ -211,6 +211,35 @@ outline: none !important; } +/* top and bottom borders on cells */ +.monaco-workbench .notebookOverlay .monaco-list .monaco-list-row.focused .cell-focus-indicator-top:before, +.monaco-workbench .notebookOverlay .monaco-list .monaco-list-row.focused .cell-focus-indicator-bottom:before, +.monaco-workbench .notebookOverlay .monaco-list .markdown-cell-row.focused:before, +.monaco-workbench .notebookOverlay .monaco-list .markdown-cell-row.focused:after{ + content: ""; + position: absolute; + width: 100%; + height: 1px; + background-color: rgba(255, 255, 255, 0.12); +} + +.monaco-workbench .notebookOverlay .monaco-list .monaco-list-row.focused .cell-focus-indicator-top:before, +.monaco-workbench .notebookOverlay .monaco-list .markdown-cell-row.focused:before { + top: 0; +} +.monaco-workbench .notebookOverlay .monaco-list .monaco-list-row.focused .cell-focus-indicator-bottom:before, +.monaco-workbench .notebookOverlay .monaco-list .markdown-cell-row.focused:after { + bottom: 0px; +} + +/* border color on light theme */ +.monaco-workbench.vs .notebookOverlay .monaco-list .monaco-list-row.focused .cell-focus-indicator-top:before, +.monaco-workbench.vs .notebookOverlay .monaco-list .monaco-list-row.focused .cell-focus-indicator-bottom:before, +.monaco-workbench.vs .notebookOverlay .monaco-list .markdown-cell-row.focused:before, +.monaco-workbench.vs .notebookOverlay .monaco-list .markdown-cell-row.focused:after { + background-color: rgba(0, 0, 0, 0.12); +} + .monaco-workbench .notebookOverlay > .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .monaco-list-row .menu.mouseover, .monaco-workbench .notebookOverlay > .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .monaco-list-row .menu:hover { cursor: pointer; From 06ba687683ee81ec9ebd4d56cd6ca86031cf9195 Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Wed, 1 Jul 2020 11:33:44 -0700 Subject: [PATCH 47/93] Bump distro ThirdPartyLicenses updates for vscode-ripgrep --- cgmanifest.json | 2 +- package.json | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/cgmanifest.json b/cgmanifest.json index 25178f2f20a34..cb9954628dd54 100644 --- a/cgmanifest.json +++ b/cgmanifest.json @@ -533,7 +533,7 @@ "git": { "name": "ripgrep", "repositoryUrl": "https://github.com/BurntSushi/ripgrep", - "commitHash": "8a7db1a918e969b85cd933d8ed9fa5285b281ba4" + "commitHash": "973de50c9ef451da2cfcdfa86f2b2711d8d6ff48" } }, "isOnlyProductionDependency": true, diff --git a/package.json b/package.json index 8b2290f71778d..f9e642482a24c 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "code-oss-dev", "version": "1.47.0", - "distro": "1586330b9cb5df91657a44dff418b9ca6c03a89e", + "distro": "246a61c6669daa9d9441c782b42579c61866cfa8", "author": { "name": "Microsoft Corporation" }, @@ -184,4 +184,4 @@ "windows-mutex": "0.3.0", "windows-process-tree": "0.2.4" } -} \ No newline at end of file +} From 6968ef84a0e1a857cc92a0ec457c15e7a7acfc2a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Wed, 1 Jul 2020 20:33:11 +0200 Subject: [PATCH 48/93] force rebase when pulling --- build/npm/postinstall.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/build/npm/postinstall.js b/build/npm/postinstall.js index 7b8b710636a70..ef8fa4a47f668 100644 --- a/build/npm/postinstall.js +++ b/build/npm/postinstall.js @@ -73,3 +73,5 @@ yarnInstall('test/automation'); // node modules required for smoketest yarnInstall('test/smoke'); // node modules required for smoketest yarnInstall('test/integration/browser'); // node modules required for integration yarnInstallBuildDependencies(); // node modules for watching, specific to host node version, not electron + +cp.execSync('git config pull.rebase true'); From e96aaa0befaabe39a4579081a6fa5e75c5e838b8 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Wed, 1 Jul 2020 12:00:24 -0700 Subject: [PATCH 49/93] Always use http for internal webview resource loading Fixes #101272 --- .../platform/webview/electron-main/webviewProtocolProvider.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/vs/platform/webview/electron-main/webviewProtocolProvider.ts b/src/vs/platform/webview/electron-main/webviewProtocolProvider.ts index 82010e716c027..11152bfd28f04 100644 --- a/src/vs/platform/webview/electron-main/webviewProtocolProvider.ts +++ b/src/vs/platform/webview/electron-main/webviewProtocolProvider.ts @@ -156,8 +156,7 @@ export class WebviewProtocolProvider extends Disposable { rewriteUri = (uri) => { if (metadata.remoteConnectionData) { if (uri.scheme === Schemas.vscodeRemote || (metadata.extensionLocation?.scheme === REMOTE_HOST_SCHEME)) { - const scheme = metadata.remoteConnectionData.host === 'localhost' || metadata.remoteConnectionData.host === '127.0.0.1' ? 'http' : 'https'; - return URI.parse(`${scheme}://${metadata.remoteConnectionData.host}:${metadata.remoteConnectionData.port}`).with({ + return URI.parse(`http://${metadata.remoteConnectionData.host}:${metadata.remoteConnectionData.port}`).with({ path: '/vscode-remote-resource', query: `tkn=${metadata.remoteConnectionData.connectionToken}&path=${encodeURIComponent(uri.path)}`, }); From 4c7d5640804ae4883ad0d679331714ef10646f5a Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Wed, 1 Jul 2020 13:29:18 -0700 Subject: [PATCH 50/93] Pick up new TS version --- extensions/package.json | 2 +- extensions/yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/extensions/package.json b/extensions/package.json index e54ff1794b2e8..7c668c9744a19 100644 --- a/extensions/package.json +++ b/extensions/package.json @@ -3,7 +3,7 @@ "version": "0.0.1", "description": "Dependencies shared by all extensions", "dependencies": { - "typescript": "3.9.5" + "typescript": "3.9.6" }, "scripts": { "postinstall": "node ./postinstall" diff --git a/extensions/yarn.lock b/extensions/yarn.lock index e0f5c7c4dd07e..d41a4ab48b565 100644 --- a/extensions/yarn.lock +++ b/extensions/yarn.lock @@ -76,10 +76,10 @@ rimraf@^3.0.2: dependencies: glob "^7.1.3" -typescript@3.9.5: - version "3.9.5" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.9.5.tgz#586f0dba300cde8be52dd1ac4f7e1009c1b13f36" - integrity sha512-hSAifV3k+i6lEoCJ2k6R2Z/rp/H3+8sdmcn5NrS3/3kE7+RyZXm9aqvxWqjEXHAd8b0pShatpcdMTvEdvAJltQ== +typescript@3.9.6: + version "3.9.6" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.9.6.tgz#8f3e0198a34c3ae17091b35571d3afd31999365a" + integrity sha512-Pspx3oKAPJtjNwE92YS05HQoY7z2SFyOpHo9MqJor3BXAGNaPUs83CuVp9VISFkSjyRfiTpmKuAYGJB7S7hOxw== wrappy@1: version "1.0.2" From 11cb67466aae047a2dd101ba0a2f8afd160bd51a Mon Sep 17 00:00:00 2001 From: Miguel Solorio Date: Wed, 1 Jul 2020 13:35:31 -0700 Subject: [PATCH 51/93] Update notebook color token names (fixes #98984) --- .../notebook/browser/media/notebook.css | 33 +++++++---- .../notebook/browser/notebookEditorWidget.ts | 56 +++++++++++++------ 2 files changed, 63 insertions(+), 26 deletions(-) diff --git a/src/vs/workbench/contrib/notebook/browser/media/notebook.css b/src/vs/workbench/contrib/notebook/browser/media/notebook.css index ddcf1ae2d0434..d74d9e44aa64f 100644 --- a/src/vs/workbench/contrib/notebook/browser/media/notebook.css +++ b/src/vs/workbench/contrib/notebook/browser/media/notebook.css @@ -215,29 +215,42 @@ .monaco-workbench .notebookOverlay .monaco-list .monaco-list-row.focused .cell-focus-indicator-top:before, .monaco-workbench .notebookOverlay .monaco-list .monaco-list-row.focused .cell-focus-indicator-bottom:before, .monaco-workbench .notebookOverlay .monaco-list .markdown-cell-row.focused:before, -.monaco-workbench .notebookOverlay .monaco-list .markdown-cell-row.focused:after{ +.monaco-workbench .notebookOverlay .monaco-list .markdown-cell-row.focused:after { content: ""; position: absolute; width: 100%; height: 1px; - background-color: rgba(255, 255, 255, 0.12); } +/* top border */ .monaco-workbench .notebookOverlay .monaco-list .monaco-list-row.focused .cell-focus-indicator-top:before, .monaco-workbench .notebookOverlay .monaco-list .markdown-cell-row.focused:before { - top: 0; + border-top: 1px solid transparent; +} + +.monaco-workbench.hc-black .notebookOverlay .monaco-list .monaco-list-row.focused.cell-editor-focus .cell-focus-indicator-top:before, +.monaco-workbench.hc-black .notebookOverlay .monaco-list .markdown-cell-row.focused.cell-editor-focus:before { + border-top-style: dashed; } + +/* bottom border */ .monaco-workbench .notebookOverlay .monaco-list .monaco-list-row.focused .cell-focus-indicator-bottom:before, .monaco-workbench .notebookOverlay .monaco-list .markdown-cell-row.focused:after { - bottom: 0px; + border-bottom: 1px solid transparent; +} + +.monaco-workbench.hc-black .notebookOverlay .monaco-list .monaco-list-row.focused.cell-editor-focus .cell-focus-indicator-bottom:before, +.monaco-workbench.hc-black .notebookOverlay .monaco-list .markdown-cell-row.focused.cell-editor-focus:after { + border-bottom-style: dashed; } -/* border color on light theme */ -.monaco-workbench.vs .notebookOverlay .monaco-list .monaco-list-row.focused .cell-focus-indicator-top:before, -.monaco-workbench.vs .notebookOverlay .monaco-list .monaco-list-row.focused .cell-focus-indicator-bottom:before, -.monaco-workbench.vs .notebookOverlay .monaco-list .markdown-cell-row.focused:before, -.monaco-workbench.vs .notebookOverlay .monaco-list .markdown-cell-row.focused:after { - background-color: rgba(0, 0, 0, 0.12); +.monaco-workbench .notebookOverlay .monaco-list .monaco-list-row.focused .cell-focus-indicator-top:before, +.monaco-workbench .notebookOverlay .monaco-list .markdown-cell-row.focused:before { + top: 0; +} +.monaco-workbench .notebookOverlay .monaco-list .monaco-list-row.focused .cell-focus-indicator-bottom:before, +.monaco-workbench .notebookOverlay .monaco-list .markdown-cell-row.focused:after { + bottom: 0px; } .monaco-workbench .notebookOverlay > .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .monaco-list-row .menu.mouseover, diff --git a/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts b/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts index 9667106b4872d..de406748cb401 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts @@ -1312,11 +1312,11 @@ export const notebookCellBorder = registerColor('notebook.cellBorderColor', { hc: PANEL_BORDER }, nls.localize('notebook.cellBorderColor', "The border color for notebook cells.")); -export const focusedEditorIndicator = registerColor('notebook.focusedEditorIndicator', { +export const focusedEditorBorderColor = registerColor('notebook.focusedEditorBorder', { light: focusBorder, dark: focusBorder, hc: focusBorder -}, nls.localize('notebook.focusedEditorIndicator', "The color of the notebook cell editor indicator.")); +}, nls.localize('notebook.focusedEditorBorder', "The color of the notebook cell editor border.")); export const cellStatusIconSuccess = registerColor('notebookStatusSuccessIcon.foreground', { light: debugIconStartForeground, @@ -1349,17 +1349,29 @@ export const CELL_TOOLBAR_SEPERATOR = registerColor('notebook.cellToolbarSeperat hc: contrastBorder }, nls.localize('cellToolbarSeperator', "The color of the seperator in the cell bottom toolbar")); -export const cellFocusBackground = registerColor('notebook.cellFocusBackground', { +export const focusedCellBackground = registerColor('notebook.focusedCellBackground', { dark: transparent(PANEL_BORDER, .4), light: transparent(listFocusBackground, .4), - hc: PANEL_BORDER -}, nls.localize('cellFocusBackground', "The background color of focused or hovered cells")); + hc: null +}, nls.localize('focusedCellBackground', "The background color of focused cells.")); + +export const cellHoverBackground = registerColor('notebook.cellHoverBackground', { + dark: transparent(focusedCellBackground, .5), + light: transparent(focusedCellBackground, .7), + hc: null +}, nls.localize('notebook.cellHoverBackground', "The background color of hovered cells.")); + +export const focusedCellBorder = registerColor('notebook.focusedCellBorder', { + dark: Color.white.transparent(0.12), + light: Color.black.transparent(0.12), + hc: focusBorder +}, nls.localize('notebook.focusedCellBorder', "The color of focused cells.")); export const focusedCellShadow = registerColor('notebook.focusedCellShadow', { dark: transparent(widgetShadow, 0.6), light: transparent(widgetShadow, 0.4), hc: Color.transparent -}, nls.localize('cellShadow', "The color of the shadow on the focused or hovered cell")); +}, nls.localize('notebook.focusedCellShadow', "The color of the shadow on the focused or hovered cell")); export const cellStatusBarItemHover = registerColor('notebook.cellStatusBarItemHoverBackground', { light: new Color(new RGBA(0, 0, 0, 0.08)), @@ -1456,18 +1468,30 @@ registerThemingParticipant((theme, collector) => { collector.addRule(`.notebookOverlay .monaco-list-row > .monaco-toolbar { border: solid 1px ${cellToolbarSeperator}; }`); } - const cellFocusBackgroundColor = theme.getColor(cellFocusBackground); - if (cellFocusBackgroundColor) { - collector.addRule(`.notebookOverlay .code-cell-row:hover .cell-focus-indicator, - .notebookOverlay .code-cell-row.focused .cell-focus-indicator, - .notebookOverlay .code-cell-row.cell-output-hover .cell-focus-indicator { background-color: ${cellFocusBackgroundColor} !important; }`); - collector.addRule(`.notebookOverlay .markdown-cell-row:hover, - .notebookOverlay .markdown-cell-row.focused { background-color: ${cellFocusBackgroundColor} !important; }`); + const focusedCellBackgroundColor = theme.getColor(focusedCellBackground); + if (focusedCellBackgroundColor) { + collector.addRule(`.notebookOverlay .code-cell-row.focused .cell-focus-indicator, + .notebookOverlay .markdown-cell-row.focused { background-color: ${focusedCellBackgroundColor} !important; }`); + } + + const cellHoverBackgroundColor = theme.getColor(cellHoverBackground); + if (cellHoverBackgroundColor) { + collector.addRule(`.notebookOverlay .code-cell-row:not(.focused):hover .cell-focus-indicator, + .notebookOverlay .code-cell-row:not(.focused).cell-output-hover .cell-focus-indicator, + .notebookOverlay .markdown-cell-row:not(.focused):hover { background-color: ${cellHoverBackgroundColor} !important; }`); } - const focusedEditorIndicatorColor = theme.getColor(focusedEditorIndicator); - if (focusedEditorIndicatorColor) { - collector.addRule(`.notebookOverlay .monaco-list-row.cell-editor-focus .cell-editor-part:before { outline: solid 1px ${focusedEditorIndicatorColor}; }`); + const focusedCellBorderColor = theme.getColor(focusedCellBorder); + collector.addRule(`.monaco-workbench .notebookOverlay .monaco-list .monaco-list-row.focused .cell-focus-indicator-top:before, + .monaco-workbench .notebookOverlay .monaco-list .monaco-list-row.focused .cell-focus-indicator-bottom:before, + .monaco-workbench .notebookOverlay .monaco-list .markdown-cell-row.focused:before, + .monaco-workbench .notebookOverlay .monaco-list .markdown-cell-row.focused:after { + border-color: ${focusedCellBorderColor} !important; + }`); + + const focusedEditorBorderColorColor = theme.getColor(focusedEditorBorderColor); + if (focusedEditorBorderColorColor) { + collector.addRule(`.notebookOverlay .monaco-list-row.cell-editor-focus .cell-editor-part:before { outline: solid 1px ${focusedEditorBorderColorColor}; }`); } const editorBorderColor = theme.getColor(notebookCellBorder); From 102a9e5e442d65af5d176bf31e6896f62b82336a Mon Sep 17 00:00:00 2001 From: Miguel Solorio Date: Wed, 1 Jul 2020 14:13:52 -0700 Subject: [PATCH 52/93] Scope markdown margins to headings --- .../workbench/contrib/notebook/browser/media/notebook.css | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/contrib/notebook/browser/media/notebook.css b/src/vs/workbench/contrib/notebook/browser/media/notebook.css index d74d9e44aa64f..d809643d2c037 100644 --- a/src/vs/workbench/contrib/notebook/browser/media/notebook.css +++ b/src/vs/workbench/contrib/notebook/browser/media/notebook.css @@ -633,8 +633,12 @@ } /* Removes bottom margin when only one item exists in markdown cell */ -.monaco-workbench .notebookOverlay .cell.markdown div *:only-child, -.monaco-workbench .notebookOverlay .cell.markdown div *:last-child { +.monaco-workbench .notebookOverlay .cell.markdown div h1:only-child, +.monaco-workbench .notebookOverlay .cell.markdown div h2:only-child, +.monaco-workbench .notebookOverlay .cell.markdown div h3:only-child, +.monaco-workbench .notebookOverlay .cell.markdown div h1:last-child, +.monaco-workbench .notebookOverlay .cell.markdown div h2:last-child, +.monaco-workbench .notebookOverlay .cell.markdown div h3:last-child { margin-bottom: 0; } From 69c2da0dd4e35642ec4fde1038774b7da4beb4c3 Mon Sep 17 00:00:00 2001 From: rebornix Date: Wed, 1 Jul 2020 14:38:33 -0700 Subject: [PATCH 53/93] avoid revert if it is not dirty --- .../workbench/contrib/notebook/browser/notebookEditorInput.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/notebook/browser/notebookEditorInput.ts b/src/vs/workbench/contrib/notebook/browser/notebookEditorInput.ts index 382fce7d99510..8dfb595f64ce7 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookEditorInput.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookEditorInput.ts @@ -133,7 +133,7 @@ export class NotebookEditorInput extends EditorInput { } async revert(group: GroupIdentifier, options?: IRevertOptions): Promise { - if (this._textModel) { + if (this._textModel && this._textModel.object.isDirty()) { await this._textModel.object.revert(options); } From b3d6826cbc96991c8b209842eac9b68c72b3134a Mon Sep 17 00:00:00 2001 From: rebornix Date: Wed, 1 Jul 2020 14:42:41 -0700 Subject: [PATCH 54/93] Revert "fix #101463." This reverts commit 4ad0de260682be6f6357606aa9ce44728294cd79. --- src/vs/workbench/browser/parts/editor/editor.contribution.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/vs/workbench/browser/parts/editor/editor.contribution.ts b/src/vs/workbench/browser/parts/editor/editor.contribution.ts index f0dbab1befe1c..78a7613f52eb3 100644 --- a/src/vs/workbench/browser/parts/editor/editor.contribution.ts +++ b/src/vs/workbench/browser/parts/editor/editor.contribution.ts @@ -457,7 +457,6 @@ MenuRegistry.appendMenuItem(MenuId.EditorTitleContext, { command: { id: editorCo MenuRegistry.appendMenuItem(MenuId.EditorTitleContext, { command: { id: editorCommands.SPLIT_EDITOR_DOWN, title: nls.localize('splitDown', "Split Down") }, group: '5_split', order: 20 }); MenuRegistry.appendMenuItem(MenuId.EditorTitleContext, { command: { id: editorCommands.SPLIT_EDITOR_LEFT, title: nls.localize('splitLeft', "Split Left") }, group: '5_split', order: 30 }); MenuRegistry.appendMenuItem(MenuId.EditorTitleContext, { command: { id: editorCommands.SPLIT_EDITOR_RIGHT, title: nls.localize('splitRight', "Split Right") }, group: '5_split', order: 40 }); -MenuRegistry.appendMenuItem(MenuId.EditorTitleContext, { command: { id: ReopenResourcesAction.ID, title: ReopenResourcesAction.LABEL }, group: '6_reopen', order: 20, when: ActiveEditorAvailableEditorIdsContext }); // Editor Title Menu MenuRegistry.appendMenuItem(MenuId.EditorTitle, { command: { id: editorCommands.TOGGLE_DIFF_SIDE_BY_SIDE, title: nls.localize('toggleInlineView', "Toggle Inline View") }, group: '1_diff', order: 10, when: ContextKeyExpr.has('isInDiffEditor') }); From 4fbaace9b638cc0c8ee71a21d4d1b585ab76abb6 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Wed, 1 Jul 2020 15:00:55 -0700 Subject: [PATCH 55/93] Remove extra parameter added for #100238 For #100238. The data for this parameter already exists on options --- src/vs/workbench/browser/contextkeys.ts | 2 +- .../contrib/customEditor/browser/customEditors.ts | 8 ++++---- .../workbench/contrib/files/browser/views/explorerView.ts | 2 +- src/vs/workbench/services/editor/browser/editorService.ts | 6 +++--- src/vs/workbench/services/editor/common/editorOpenWith.ts | 8 +++++--- src/vs/workbench/services/editor/common/editorService.ts | 4 ++-- 6 files changed, 16 insertions(+), 14 deletions(-) diff --git a/src/vs/workbench/browser/contextkeys.ts b/src/vs/workbench/browser/contextkeys.ts index d21f3e967f087..118699c1986c7 100644 --- a/src/vs/workbench/browser/contextkeys.ts +++ b/src/vs/workbench/browser/contextkeys.ts @@ -210,7 +210,7 @@ export class WorkbenchContextKeysHandler extends Disposable { this.activeEditorContext.set(activeEditorPane.getId()); this.activeEditorIsReadonly.set(activeEditorPane.input.isReadonly()); - const editors = activeEditorPane.input.resource ? this.editorService.getEditorOverrides(activeEditorPane.input.resource, undefined, activeGroup, undefined) : []; + const editors = activeEditorPane.input.resource ? this.editorService.getEditorOverrides(activeEditorPane.input.resource, undefined, activeGroup) : []; this.activeEditorAvailableEditorIds.set(editors.map(([_, entry]) => entry.id).join(',')); } else { this.activeEditorContext.reset(); diff --git a/src/vs/workbench/contrib/customEditor/browser/customEditors.ts b/src/vs/workbench/contrib/customEditor/browser/customEditors.ts index 7334fa865623d..787ffd48fd8d2 100644 --- a/src/vs/workbench/contrib/customEditor/browser/customEditors.ts +++ b/src/vs/workbench/contrib/customEditor/browser/customEditors.ts @@ -451,7 +451,7 @@ export class CustomEditorContribution extends Disposable implements IWorkbenchCo open: (editor, options, group) => { return this.onEditorOpening(editor, options, group); }, - getEditorOverrides: (resource: URI, _options: IEditorOptions | undefined, group: IEditorGroup | undefined, id: string | undefined): IOpenEditorOverrideEntry[] => { + getEditorOverrides: (resource: URI, options: IEditorOptions | undefined, group: IEditorGroup | undefined): IOpenEditorOverrideEntry[] => { const currentEditor = group?.editors.find(editor => isEqual(editor.resource, resource)); const defaultEditorOverride: IOpenEditorOverrideEntry = { @@ -468,14 +468,14 @@ export class CustomEditorContribution extends Disposable implements IWorkbenchCo }; }; - if (typeof id === 'string') { + if (typeof options?.override === 'string') { // A specific override was requested. Only return it. - if (id === defaultEditorOverride.id) { + if (options.override === defaultEditorOverride.id) { return [defaultEditorOverride]; } - const matchingEditor = this.customEditorService.getCustomEditor(id); + const matchingEditor = this.customEditorService.getCustomEditor(options.override); return matchingEditor ? [toOverride(matchingEditor)] : []; } diff --git a/src/vs/workbench/contrib/files/browser/views/explorerView.ts b/src/vs/workbench/contrib/files/browser/views/explorerView.ts index 158acc0adb3b4..66d9416279453 100644 --- a/src/vs/workbench/contrib/files/browser/views/explorerView.ts +++ b/src/vs/workbench/contrib/files/browser/views/explorerView.ts @@ -486,7 +486,7 @@ export class ExplorerView extends ViewPane { this.rootContext.set(!stat || (stat && stat.isRoot)); if (resource) { - const overrides = resource ? this.editorService.getEditorOverrides(resource, undefined, undefined, undefined) : []; + const overrides = resource ? this.editorService.getEditorOverrides(resource, undefined, undefined) : []; this.availableEditorIdsContext.set(overrides.map(([, entry]) => entry.id).join(',')); } else { this.availableEditorIdsContext.reset(); diff --git a/src/vs/workbench/services/editor/browser/editorService.ts b/src/vs/workbench/services/editor/browser/editorService.ts index 0e04abf93f535..4cd489bac5625 100644 --- a/src/vs/workbench/services/editor/browser/editorService.ts +++ b/src/vs/workbench/services/editor/browser/editorService.ts @@ -490,10 +490,10 @@ export class EditorService extends Disposable implements EditorServiceImpl { return toDisposable(() => remove()); } - getEditorOverrides(resource: URI, options: IEditorOptions | undefined, group: IEditorGroup | undefined, id: string | undefined): [IOpenEditorOverrideHandler, IOpenEditorOverrideEntry][] { + getEditorOverrides(resource: URI, options: IEditorOptions | undefined, group: IEditorGroup | undefined): [IOpenEditorOverrideHandler, IOpenEditorOverrideEntry][] { const overrides = []; for (const handler of this.openEditorHandlers) { - const handlers = handler.getEditorOverrides ? handler.getEditorOverrides(resource, options, group, id).map(val => [handler, val] as [IOpenEditorOverrideHandler, IOpenEditorOverrideEntry]) : []; + const handlers = handler.getEditorOverrides ? handler.getEditorOverrides(resource, options, group).map(val => [handler, val] as [IOpenEditorOverrideHandler, IOpenEditorOverrideEntry]) : []; overrides.push(...handlers); } @@ -1347,7 +1347,7 @@ export class DelegatingEditorService implements IEditorService { isOpen(editor: IEditorInput | IResourceEditorInput): boolean { return this.editorService.isOpen(editor as IResourceEditorInput /* TS fail */); } overrideOpenEditor(handler: IOpenEditorOverrideHandler): IDisposable { return this.editorService.overrideOpenEditor(handler); } - getEditorOverrides(resource: URI, options: IEditorOptions | undefined, group: IEditorGroup | undefined, id: string | undefined) { return this.editorService.getEditorOverrides(resource, options, group, id); } + getEditorOverrides(resource: URI, options: IEditorOptions | undefined, group: IEditorGroup | undefined) { return this.editorService.getEditorOverrides(resource, options, group); } invokeWithinEditorContext(fn: (accessor: ServicesAccessor) => T): T { return this.editorService.invokeWithinEditorContext(fn); } diff --git a/src/vs/workbench/services/editor/common/editorOpenWith.ts b/src/vs/workbench/services/editor/common/editorOpenWith.ts index 115cc98c03989..af8462e5f4230 100644 --- a/src/vs/workbench/services/editor/common/editorOpenWith.ts +++ b/src/vs/workbench/services/editor/common/editorOpenWith.ts @@ -42,14 +42,16 @@ export async function openEditorWith( return; } - const allEditorOverrides = getAllAvailableEditors(resource, id, options, group, editorService); + const overrideOptions = { ...options, override: id }; + + const allEditorOverrides = getAllAvailableEditors(resource, id, overrideOptions, group, editorService); if (!allEditorOverrides.length) { return; } const overrideToUse = typeof id === 'string' && allEditorOverrides.find(([_, entry]) => entry.id === id); if (overrideToUse) { - return overrideToUse[0].open(input, { ...options, override: id }, group, OpenEditorContext.NEW_EDITOR)?.override; + return overrideToUse[0].open(input, overrideOptions, group, OpenEditorContext.NEW_EDITOR)?.override; } // Prompt @@ -134,7 +136,7 @@ export function getAllAvailableEditors( editorService: IEditorService ): Array<[IOpenEditorOverrideHandler, IOpenEditorOverrideEntry]> { const fileEditorInputFactory = Registry.as(EditorExtensions.EditorInputFactories).getFileEditorInputFactory(); - const overrides = editorService.getEditorOverrides(resource, options, group, id); + const overrides = editorService.getEditorOverrides(resource, options, group); if (!overrides.some(([_, entry]) => entry.id === DEFAULT_EDITOR_ID)) { overrides.unshift([ { diff --git a/src/vs/workbench/services/editor/common/editorService.ts b/src/vs/workbench/services/editor/common/editorService.ts index f85b0c6ba1cd9..8e4816612963b 100644 --- a/src/vs/workbench/services/editor/common/editorService.ts +++ b/src/vs/workbench/services/editor/common/editorService.ts @@ -36,7 +36,7 @@ export interface IOpenEditorOverrideEntry { export interface IOpenEditorOverrideHandler { open(editor: IEditorInput, options: IEditorOptions | ITextEditorOptions | undefined, group: IEditorGroup, context: OpenEditorContext): IOpenEditorOverride | undefined; - getEditorOverrides?(resource: URI, options: IEditorOptions | undefined, group: IEditorGroup | undefined, id: string | undefined): IOpenEditorOverrideEntry[]; + getEditorOverrides?(resource: URI, options: IEditorOptions | undefined, group: IEditorGroup | undefined): IOpenEditorOverrideEntry[]; } export interface IOpenEditorOverride { @@ -236,7 +236,7 @@ export interface IEditorService { /** * Get all available editor overrides for the editor input. */ - getEditorOverrides(resource: URI, options: IEditorOptions | undefined, group: IEditorGroup | undefined, id: string | undefined): [IOpenEditorOverrideHandler, IOpenEditorOverrideEntry][]; + getEditorOverrides(resource: URI, options: IEditorOptions | undefined, group: IEditorGroup | undefined): [IOpenEditorOverrideHandler, IOpenEditorOverrideEntry][]; /** * Allows to override the opening of editors by installing a handler that will From 94c2ccd88138d6ec3e7e8e55fb2f692b87b73246 Mon Sep 17 00:00:00 2001 From: Connor Peet Date: Wed, 1 Jul 2020 16:56:59 -0700 Subject: [PATCH 56/93] debug: update js-debug --- product.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/product.json b/product.json index 11cb35a432778..3165e58d54317 100644 --- a/product.json +++ b/product.json @@ -90,7 +90,7 @@ }, { "name": "ms-vscode.js-debug", - "version": "1.46.2", + "version": "1.47.1", "repo": "https://github.com/Microsoft/vscode-js-debug", "metadata": { "id": "25629058-ddac-4e17-abba-74678e126c5d", From 5dc7025c1ef092381f9c7ac4b2fb5640aa8730d2 Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Wed, 1 Jul 2020 17:09:56 -0700 Subject: [PATCH 57/93] Bump node-debug2 --- product.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/product.json b/product.json index 3165e58d54317..2d4bdaa2d5fe2 100644 --- a/product.json +++ b/product.json @@ -45,7 +45,7 @@ }, { "name": "ms-vscode.node-debug2", - "version": "1.42.4", + "version": "1.42.5", "repo": "https://github.com/Microsoft/vscode-node-debug2", "metadata": { "id": "36d19e17-7569-4841-a001-947eb18602b2", From 71776589163b831768c408bcad2a87d73941bbb6 Mon Sep 17 00:00:00 2001 From: Jackson Kearl Date: Wed, 1 Jul 2020 18:01:45 -0700 Subject: [PATCH 58/93] Revert "Fix #98766 - Reloading a dirty saved search editor causes a phantom tab to appear" This reverts commit 028241b16005863c63d96505e54fb95a02dad59f. This fixes #99621, but re-introduces #98766 I'm not sure of a way to remove both bugs, it will likely involve large refactorings. --- .../workbench/contrib/searchEditor/browser/searchEditorInput.ts | 2 +- .../workbench/contrib/searchEditor/browser/searchEditorModel.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/contrib/searchEditor/browser/searchEditorInput.ts b/src/vs/workbench/contrib/searchEditor/browser/searchEditorInput.ts index 8c29e07887330..36a7e3037d23b 100644 --- a/src/vs/workbench/contrib/searchEditor/browser/searchEditorInput.ts +++ b/src/vs/workbench/contrib/searchEditor/browser/searchEditorInput.ts @@ -110,7 +110,7 @@ export class SearchEditorInput extends EditorInput { const input = this; const workingCopyAdapter = new class implements IWorkingCopy { - readonly resource = input.backingUri ?? input.modelUri; + readonly resource = input.modelUri; get name() { return input.getName(); } readonly capabilities = input.isUntitled() ? WorkingCopyCapabilities.Untitled : 0; readonly onDidChangeDirty = input.onDidChangeDirty; diff --git a/src/vs/workbench/contrib/searchEditor/browser/searchEditorModel.ts b/src/vs/workbench/contrib/searchEditor/browser/searchEditorModel.ts index 038ddda46724f..fd868994e0867 100644 --- a/src/vs/workbench/contrib/searchEditor/browser/searchEditorModel.ts +++ b/src/vs/workbench/contrib/searchEditor/browser/searchEditorModel.ts @@ -34,7 +34,7 @@ export class SearchEditorModel { @IModeService private readonly modeService: IModeService) { this.onModelResolved = new Promise(resolve => this.resolveContents = resolve); this.onModelResolved.then(model => this.cachedContentsModel = model); - this.ongoingResolve = backupService.resolve(existingData.backingUri ?? modelUri) + this.ongoingResolve = backupService.resolve(modelUri) .then(backup => modelService.getModel(modelUri) ?? (backup ? modelService.createModel(backup.value, modeService.create('search-result'), modelUri) : undefined)) .then(model => { if (model) { this.resolveContents(model); } }); } From 04545fa88043fd10d1f3edefd26be1b8245b516f Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Wed, 1 Jul 2020 18:42:31 -0700 Subject: [PATCH 59/93] Fix clicking on left output margin of cell Fix #101546 --- src/vs/workbench/contrib/notebook/browser/media/notebook.css | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/vs/workbench/contrib/notebook/browser/media/notebook.css b/src/vs/workbench/contrib/notebook/browser/media/notebook.css index d809643d2c037..de47d0d95e48b 100644 --- a/src/vs/workbench/contrib/notebook/browser/media/notebook.css +++ b/src/vs/workbench/contrib/notebook/browser/media/notebook.css @@ -440,8 +440,7 @@ position: absolute; box-sizing: border-box; top: 0px; - visibility: hidden; - opacity: 1; + opacity: 0; } .monaco-workbench .notebookOverlay .monaco-list .monaco-list-row .cell-focus-indicator-side { @@ -470,7 +469,7 @@ .monaco-workbench .notebookOverlay .monaco-list .monaco-list-row:hover .cell-focus-indicator, .monaco-workbench .notebookOverlay .monaco-list .monaco-list-row.cell-output-hover .cell-focus-indicator, .monaco-workbench .notebookOverlay .monaco-list .monaco-list-row.focused .cell-focus-indicator { - visibility: visible; + opacity: 1; } .monaco-workbench .notebookOverlay .monaco-list-row .cell-editor-part:before { From 8d699df76bc54aedda370574acd2ccfe945bad96 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Thu, 2 Jul 2020 08:35:28 +0200 Subject: [PATCH 60/93] Fix #100348 --- .../userDataSync/common/userDataAutoSyncService.ts | 10 ++++++++-- .../contrib/userDataSync/browser/userDataSync.ts | 12 ++++++++++-- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/src/vs/platform/userDataSync/common/userDataAutoSyncService.ts b/src/vs/platform/userDataSync/common/userDataAutoSyncService.ts index 62dd7cc144c41..cb5c8d665f718 100644 --- a/src/vs/platform/userDataSync/common/userDataAutoSyncService.ts +++ b/src/vs/platform/userDataSync/common/userDataAutoSyncService.ts @@ -219,8 +219,14 @@ export class UserDataAutoSyncService extends UserDataAutoSyncEnablementService i this.telemetryService.publicLog2<{ code: string }, AutoSyncErrorClassification>(`autosync/error`, { code: userDataSyncError.code }); } - // Turned off from another device or session got expired - if (userDataSyncError.code === UserDataSyncErrorCode.TurnedOff || userDataSyncError.code === UserDataSyncErrorCode.SessionExpired) { + // Session got expired + if (userDataSyncError.code === UserDataSyncErrorCode.SessionExpired) { + await this.turnOff(false, true /* force soft turnoff on error */); + this.logService.info('Auto Sync: Turned off sync because current session is expired'); + } + + // Turned off from another device + if (userDataSyncError.code === UserDataSyncErrorCode.TurnedOff) { await this.turnOff(false, true /* force soft turnoff on error */); this.logService.info('Auto Sync: Turned off sync because sync is turned off in the cloud'); } diff --git a/src/vs/workbench/contrib/userDataSync/browser/userDataSync.ts b/src/vs/workbench/contrib/userDataSync/browser/userDataSync.ts index a7db7c25c79f3..436487eab2fee 100644 --- a/src/vs/workbench/contrib/userDataSync/browser/userDataSync.ts +++ b/src/vs/workbench/contrib/userDataSync/browser/userDataSync.ts @@ -270,11 +270,19 @@ export class UserDataSyncWorkbenchContribution extends Disposable implements IWo private onAutoSyncError(error: UserDataSyncError): void { switch (error.code) { - case UserDataSyncErrorCode.TurnedOff: case UserDataSyncErrorCode.SessionExpired: this.notificationService.notify({ severity: Severity.Info, - message: localize('turned off', "Preferences sync was turned off from another device."), + message: localize('session expired', "Preferences sync was turned off because current session is expired, please sign in again to turn on sync."), + actions: { + primary: [new Action('turn on sync', localize('turn on sync', "Turn on Preferences Sync..."), undefined, true, () => this.turnOn())] + } + }); + break; + case UserDataSyncErrorCode.TurnedOff: + this.notificationService.notify({ + severity: Severity.Info, + message: localize('turned off', "Preferences sync was turned off from another device, please sign in again to turn on sync."), actions: { primary: [new Action('turn on sync', localize('turn on sync', "Turn on Preferences Sync..."), undefined, true, () => this.turnOn())] } From ea2ad328385afe387193de315fc8e40509fd1383 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Thu, 2 Jul 2020 09:19:22 +0200 Subject: [PATCH 61/93] storage - remove unused code --- src/vs/platform/storage/node/storageService.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/platform/storage/node/storageService.ts b/src/vs/platform/storage/node/storageService.ts index 43d0332fa2838..703b7a841a2b5 100644 --- a/src/vs/platform/storage/node/storageService.ts +++ b/src/vs/platform/storage/node/storageService.ts @@ -263,7 +263,7 @@ export class NativeStorageService extends Disposable implements IStorageService async migrate(toWorkspace: IWorkspaceInitializationPayload): Promise { if (this.workspaceStoragePath === SQLiteStorageDatabase.IN_MEMORY_PATH) { - return Promise.resolve(); // no migration needed if running in memory + return; // no migration needed if running in memory } // Close workspace DB to be able to copy From cf6efa68b5569bc240840abdcb799746357a79fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Thu, 2 Jul 2020 09:47:38 +0200 Subject: [PATCH 62/93] SCM UX exploration #101103 --- src/vs/workbench/contrib/scm/browser/media/scm.css | 7 ++++--- .../workbench/contrib/scm/browser/scmViewPane.ts | 14 +++----------- 2 files changed, 7 insertions(+), 14 deletions(-) diff --git a/src/vs/workbench/contrib/scm/browser/media/scm.css b/src/vs/workbench/contrib/scm/browser/media/scm.css index e2ae17bfd60de..c1cf75e6d262a 100644 --- a/src/vs/workbench/contrib/scm/browser/media/scm.css +++ b/src/vs/workbench/contrib/scm/browser/media/scm.css @@ -15,9 +15,6 @@ .scm-view .count { display: flex; -} - -.scm-view .count { margin-left: 6px; } @@ -39,6 +36,10 @@ overflow: hidden; } +.scm-view .scm-provider > .label > .name { + font-weight: bold; +} + .scm-view .scm-provider > .label > .description { opacity: 0.7; margin-left: 0.5em; diff --git a/src/vs/workbench/contrib/scm/browser/scmViewPane.ts b/src/vs/workbench/contrib/scm/browser/scmViewPane.ts index 0925d7059e90a..762cf40d91a01 100644 --- a/src/vs/workbench/contrib/scm/browser/scmViewPane.ts +++ b/src/vs/workbench/contrib/scm/browser/scmViewPane.ts @@ -6,7 +6,7 @@ import 'vs/css!./media/scm'; import { Event, Emitter } from 'vs/base/common/event'; import { basename, dirname, isEqual } from 'vs/base/common/resources'; -import { IDisposable, Disposable, DisposableStore, combinedDisposable, toDisposable } from 'vs/base/common/lifecycle'; +import { IDisposable, Disposable, DisposableStore, combinedDisposable } from 'vs/base/common/lifecycle'; import { ViewPane, IViewPaneOptions } from 'vs/workbench/browser/parts/views/viewPaneContainer'; import { append, $, addClass, toggleClass, removeClass, Dimension } from 'vs/base/browser/dom'; import { IListVirtualDelegate, IIdentityProvider } from 'vs/base/browser/ui/list/list'; @@ -176,10 +176,7 @@ class RepositoryRenderer implements ICompressibleTreeRenderer removeClass(row, 'scm-provider-row')); + addClass(container.parentElement!.parentElement!.querySelector('.monaco-tl-twistie')! as HTMLElement, 'force-twistie'); const provider = append(container, $('.scm-provider')); const label = append(provider, $('.label')); @@ -193,7 +190,7 @@ class RepositoryRenderer implements ICompressibleTreeRenderer toggleClass(provider, 'active', e)); const disposable = Disposable.None; - const templateDisposable = combinedDisposable(rowDisposable, visibilityDisposable, toolBar, badgeStyler); + const templateDisposable = combinedDisposable(visibilityDisposable, toolBar, badgeStyler); return { name, description, countContainer, count, toolBar, disposable, templateDisposable }; } @@ -1885,9 +1882,4 @@ registerThemingParticipant((theme, collector) => { if (repositoryStatusActionsBorderColor) { collector.addRule(`.scm-view .scm-provider > .status > .monaco-action-bar > .actions-container { border-color: ${repositoryStatusActionsBorderColor}; }`); } - - const providerSeparatorBorderColor = theme.getColor(scmProviderSeparatorBorderColor); - if (providerSeparatorBorderColor) { - collector.addRule(`.scm-view .scm-provider-row:not([data-index="0"]) { border-top: 1px dashed ${providerSeparatorBorderColor}; }`); - } }); From d6adf8aaf2d026bc5abbf78bbfecc35d949772c2 Mon Sep 17 00:00:00 2001 From: Eric Amodio Date: Thu, 2 Jul 2020 03:49:04 -0400 Subject: [PATCH 63/93] Re-adds command --- extensions/github-browser/package.json | 9 ++++ extensions/github-browser/src/extension.ts | 48 +++++++++++----------- 2 files changed, 33 insertions(+), 24 deletions(-) diff --git a/extensions/github-browser/package.json b/extensions/github-browser/package.json index 6e3c071b70e8f..9938e25ed5436 100644 --- a/extensions/github-browser/package.json +++ b/extensions/github-browser/package.json @@ -21,6 +21,11 @@ "main": "./out/extension.js", "contributes": { "commands": [ + { + "command": "githubBrowser.openRepository", + "title": "Open GitHub Repository...", + "category": "GitHub Browser" + }, { "command": "githubBrowser.commit", "title": "Commit", @@ -48,6 +53,10 @@ ], "menus": { "commandPalette": [ + { + "command": "githubBrowser.openRepository", + "when": "config.githubBrowser.openRepository" + }, { "command": "githubBrowser.commit", "when": "false" diff --git a/extensions/github-browser/src/extension.ts b/extensions/github-browser/src/extension.ts index 63cb1441a4827..8a454c693b140 100644 --- a/extensions/github-browser/src/extension.ts +++ b/extensions/github-browser/src/extension.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { ExtensionContext, Uri, workspace } from 'vscode'; +import { commands, ExtensionContext, Uri, window, workspace } from 'vscode'; import { ChangeStore } from './changeStore'; import { ContextStore } from './contextStore'; import { VirtualFS } from './fs'; @@ -11,7 +11,7 @@ import { GitHubApiContext, GitHubApi } from './github/api'; import { GitHubFS } from './github/fs'; import { VirtualSCM } from './scm'; -// const repositoryRegex = /^(?:(?:https:\/\/)?github.com\/)?([^\/]+)\/([^\/]+?)(?:\/|.git|$)/i; +const repositoryRegex = /^(?:(?:https:\/\/)?github.com\/)?([^\/]+)\/([^\/]+?)(?:\/|.git|$)/i; export function activate(context: ExtensionContext) { const contextStore = new ContextStore(context.workspaceState, GitHubFS.scheme); @@ -28,23 +28,23 @@ export function activate(context: ExtensionContext) { new VirtualSCM(GitHubFS.scheme, githubApi, changeStore) ); - // commands.registerCommand('githubBrowser.openRepository', async () => { - // const value = await window.showInputBox({ - // placeHolder: 'e.g. https://github.com/microsoft/vscode', - // prompt: 'Enter a GitHub repository url', - // validateInput: value => repositoryRegex.test(value) ? undefined : 'Invalid repository url' - // }); + commands.registerCommand('githubBrowser.openRepository', async () => { + const value = await window.showInputBox({ + placeHolder: 'e.g. https://github.com/microsoft/vscode', + prompt: 'Enter a GitHub repository url', + validateInput: value => repositoryRegex.test(value) ? undefined : 'Invalid repository url' + }); - // if (value) { - // const match = repositoryRegex.exec(value); - // if (match) { - // const [, owner, repo] = match; + if (value) { + const match = repositoryRegex.exec(value); + if (match) { + const [, owner, repo] = match; - // const uri = Uri.parse(`codespace://HEAD/${owner}/${repo}`); - // openWorkspace(uri, repo, 'currentWindow'); - // } - // } - // }); + const uri = Uri.parse(`codespace://HEAD/${owner}/${repo}`); + openWorkspace(uri, repo, 'currentWindow'); + } + } + }); } export function getRelativePath(rootUri: Uri, uri: Uri) { @@ -63,11 +63,11 @@ export function isDescendent(folderPath: string, filePath: string) { return folderPath.length === 0 || filePath.startsWith(folderPath.endsWith('/') ? folderPath : `${folderPath}/`); } -// function openWorkspace(uri: Uri, name: string, location: 'currentWindow' | 'newWindow' | 'addToCurrentWorkspace') { -// if (location === 'addToCurrentWorkspace') { -// const count = (workspace.workspaceFolders && workspace.workspaceFolders.length) || 0; -// return workspace.updateWorkspaceFolders(count, 0, { uri: uri, name: name }); -// } +function openWorkspace(uri: Uri, name: string, location: 'currentWindow' | 'newWindow' | 'addToCurrentWorkspace') { + if (location === 'addToCurrentWorkspace') { + const count = (workspace.workspaceFolders && workspace.workspaceFolders.length) || 0; + return workspace.updateWorkspaceFolders(count, 0, { uri: uri, name: name }); + } -// return commands.executeCommand('vscode.openFolder', uri, location === 'newWindow'); -// } + return commands.executeCommand('vscode.openFolder', uri, location === 'newWindow'); +} From 62939fbe124bc991b93f887ed497c28c4e815838 Mon Sep 17 00:00:00 2001 From: Eric Amodio Date: Thu, 2 Jul 2020 03:49:19 -0400 Subject: [PATCH 64/93] Adds branch support --- resources/serverless/code-web.js | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/resources/serverless/code-web.js b/resources/serverless/code-web.js index bee6ca5b7133b..4345136b62516 100644 --- a/resources/serverless/code-web.js +++ b/resources/serverless/code-web.js @@ -232,20 +232,23 @@ async function handleRoot(req, res) { if (match) { const qs = new URLSearchParams(match[1]); - let ghPath = qs.get('gh'); - if (ghPath) { - if (!ghPath.startsWith('/')) { - ghPath = '/' + ghPath; + let gh = qs.get('gh'); + if (gh) { + if (gh.startsWith('/')) { + gh = gh.substr(1); } - folderUri = { scheme: 'github', authority: 'HEAD', path: ghPath }; - } else { - let csPath = qs.get('cs'); - if (csPath) { - if (!csPath.startsWith('/')) { - csPath = '/' + csPath; + const [owner, repo, ...branch] = gh.split('/', 3); + folderUri = { scheme: 'github', authority: branch.join('/') || 'HEAD', path: `/${owner}/${repo}` }; + } else { + let cs = qs.get('cs'); + if (cs) { + if (cs.startsWith('/')) { + cs = cs.substr(1); } - folderUri = { scheme: 'codespace', authority: 'HEAD', path: csPath }; + + const [owner, repo, ...branch] = cs.split('/'); + folderUri = { scheme: 'codespace', authority: branch.join('/') || 'HEAD', path: `/${owner}/${repo}` }; } } } From d3f4b7ec30733e2548b49c3de90e028224b0617c Mon Sep 17 00:00:00 2001 From: Eric Amodio Date: Thu, 2 Jul 2020 03:54:05 -0400 Subject: [PATCH 65/93] Fixes clearing context on reload if no changes Adds statusbar entry Reworks context storage a bit --- extensions/github-browser/src/changeStore.ts | 40 ++++---- extensions/github-browser/src/contextStore.ts | 35 +++++-- extensions/github-browser/src/extension.ts | 15 ++- extensions/github-browser/src/fs.ts | 24 ++--- extensions/github-browser/src/github/api.ts | 87 +++++++++------- extensions/github-browser/src/github/fs.ts | 4 +- extensions/github-browser/src/scm.ts | 10 +- extensions/github-browser/src/statusbar.ts | 99 +++++++++++++++++++ 8 files changed, 222 insertions(+), 92 deletions(-) create mode 100644 extensions/github-browser/src/statusbar.ts diff --git a/extensions/github-browser/src/changeStore.ts b/extensions/github-browser/src/changeStore.ts index 641bf1524fd32..f4bd624b9e753 100644 --- a/extensions/github-browser/src/changeStore.ts +++ b/extensions/github-browser/src/changeStore.ts @@ -47,31 +47,17 @@ function fromSerialized(operations: StoredOperation): Operation { return { ...operations, uri: Uri.parse(operations.uri) }; } -interface CreatedFileChangeStoreEvent { - type: 'created'; - rootUri: Uri; - uri: Uri; -} - -interface ChangedFileChangeStoreEvent { - type: 'changed'; - rootUri: Uri; - uri: Uri; -} - -interface DeletedFileChangeStoreEvent { - type: 'deleted'; +export interface ChangeStoreEvent { + type: 'created' | 'changed' | 'deleted'; rootUri: Uri; uri: Uri; } -type ChangeStoreEvent = CreatedFileChangeStoreEvent | ChangedFileChangeStoreEvent | DeletedFileChangeStoreEvent; - function toChangeStoreEvent(operation: Operation | StoredOperation, rootUri: Uri, uri?: Uri): ChangeStoreEvent { return { type: operation.type, rootUri: rootUri, - uri: uri ?? (typeof operation.uri === 'string' ? Uri.parse(operation.uri) : operation.uri) + uri: uri ?? (typeof operation.uri === 'string' ? Uri.parse(operation.uri) : operation.uri), }; } @@ -82,6 +68,8 @@ export interface IChangeStore { discard(uri: Uri): Promise; discardAll(rootUri: Uri): Promise; + hasChanges(rootUri: Uri): boolean; + getChanges(rootUri: Uri): Operation[]; getContent(uri: Uri): string | undefined; @@ -116,9 +104,15 @@ export class ChangeStore implements IChangeStore, IWritableChangeStore { await this.saveWorkingOperations(rootUri, undefined); + const events: ChangeStoreEvent[] = []; + for (const operation of operations) { await this.discardWorkingContent(operation.uri); - this._onDidChange.fire(toChangeStoreEvent(operation, rootUri)); + events.push(toChangeStoreEvent(operation, rootUri)); + } + + for (const e of events) { + this._onDidChange.fire(e); } } @@ -143,7 +137,7 @@ export class ChangeStore implements IChangeStore, IWritableChangeStore { this._onDidChange.fire({ type: operation.type === 'created' ? 'deleted' : operation.type === 'deleted' ? 'created' : 'changed', rootUri: rootUri, - uri: uri + uri: uri, }); } @@ -152,9 +146,15 @@ export class ChangeStore implements IChangeStore, IWritableChangeStore { await this.saveWorkingOperations(rootUri, undefined); + const events: ChangeStoreEvent[] = []; + for (const operation of operations) { await this.discardWorkingContent(operation.uri); - this._onDidChange.fire(toChangeStoreEvent(operation, rootUri)); + events.push(toChangeStoreEvent(operation, rootUri)); + } + + for (const e of events) { + this._onDidChange.fire(e); } } diff --git a/extensions/github-browser/src/contextStore.ts b/extensions/github-browser/src/contextStore.ts index 20e3491766244..80286445dfebc 100644 --- a/extensions/github-browser/src/contextStore.ts +++ b/extensions/github-browser/src/contextStore.ts @@ -4,9 +4,13 @@ *--------------------------------------------------------------------------------------------*/ 'use strict'; -import { Event, EventEmitter, Memento, Uri } from 'vscode'; +import { Event, EventEmitter, Memento, Uri, workspace } from 'vscode'; -export const contextKeyPrefix = 'github.context|'; +export interface WorkspaceFolderContext { + context: T; + name: string; + folderUri: Uri; +} export class ContextStore { private _onDidChange = new EventEmitter(); @@ -14,23 +18,36 @@ export class ContextStore { return this._onDidChange.event; } - constructor(private readonly memento: Memento, private readonly scheme: string) { } + constructor( + private readonly scheme: string, + private readonly originalScheme: string, + private readonly memento: Memento, + ) { } delete(uri: Uri) { return this.set(uri, undefined); } get(uri: Uri): T | undefined { - return this.memento.get(`${contextKeyPrefix}${uri.toString()}`); + return this.memento.get(`${this.originalScheme}.context|${this.getOriginalResource(uri).toString()}`); } + getForWorkspace(): WorkspaceFolderContext[] { + const folders = workspace.workspaceFolders?.filter(f => f.uri.scheme === this.scheme || f.uri.scheme === this.originalScheme) ?? []; + return folders.map(f => ({ context: this.get(f.uri)!, name: f.name, folderUri: f.uri })).filter(c => c.context !== undefined); + } async set(uri: Uri, context: T | undefined) { - if (uri.scheme !== this.scheme) { - throw new Error(`Invalid context scheme: ${uri.scheme}`); - } - - await this.memento.update(`${contextKeyPrefix}${uri.toString()}`, context); + uri = this.getOriginalResource(uri); + await this.memento.update(`${this.originalScheme}.context|${uri.toString()}`, context); this._onDidChange.fire(uri); } + + getOriginalResource(uri: Uri): Uri { + return uri.with({ scheme: this.originalScheme }); + } + + getWorkspaceResource(uri: Uri): Uri { + return uri.with({ scheme: this.scheme }); + } } diff --git a/extensions/github-browser/src/extension.ts b/extensions/github-browser/src/extension.ts index 8a454c693b140..893daf93c5866 100644 --- a/extensions/github-browser/src/extension.ts +++ b/extensions/github-browser/src/extension.ts @@ -10,22 +10,24 @@ import { VirtualFS } from './fs'; import { GitHubApiContext, GitHubApi } from './github/api'; import { GitHubFS } from './github/fs'; import { VirtualSCM } from './scm'; +import { StatusBar } from './statusbar'; const repositoryRegex = /^(?:(?:https:\/\/)?github.com\/)?([^\/]+)\/([^\/]+?)(?:\/|.git|$)/i; -export function activate(context: ExtensionContext) { - const contextStore = new ContextStore(context.workspaceState, GitHubFS.scheme); +export async function activate(context: ExtensionContext) { + const contextStore = new ContextStore('codespace', GitHubFS.scheme, context.workspaceState); const changeStore = new ChangeStore(context.workspaceState); const githubApi = new GitHubApi(contextStore); const gitHubFS = new GitHubFS(githubApi); - const virtualFS = new VirtualFS('codespace', GitHubFS.scheme, contextStore, changeStore, gitHubFS); + const virtualFS = new VirtualFS('codespace', contextStore, changeStore, gitHubFS); context.subscriptions.push( githubApi, gitHubFS, virtualFS, - new VirtualSCM(GitHubFS.scheme, githubApi, changeStore) + new VirtualSCM(GitHubFS.scheme, githubApi, changeStore), + new StatusBar(contextStore, changeStore), ); commands.registerCommand('githubBrowser.openRepository', async () => { @@ -63,6 +65,11 @@ export function isDescendent(folderPath: string, filePath: string) { return folderPath.length === 0 || filePath.startsWith(folderPath.endsWith('/') ? folderPath : `${folderPath}/`); } +const shaRegex = /^[0-9a-f]{40}$/; +export function isSha(ref: string) { + return shaRegex.test(ref); +} + function openWorkspace(uri: Uri, name: string, location: 'currentWindow' | 'newWindow' | 'addToCurrentWorkspace') { if (location === 'addToCurrentWorkspace') { const count = (workspace.workspaceFolders && workspace.workspaceFolders.length) || 0; diff --git a/extensions/github-browser/src/fs.ts b/extensions/github-browser/src/fs.ts index 84dce33b1a872..56af40f21bae0 100644 --- a/extensions/github-browser/src/fs.ts +++ b/extensions/github-browser/src/fs.ts @@ -43,26 +43,22 @@ export class VirtualFS implements FileSystemProvider, FileSearchProvider, TextSe constructor( readonly scheme: string, - private readonly originalScheme: string, - contextStore: ContextStore, + private readonly contextStore: ContextStore, private readonly changeStore: IWritableChangeStore, private readonly fs: FileSystemProvider & FileSearchProvider & TextSearchProvider ) { // TODO@eamodio listen for workspace folder changes - for (const folder of workspace.workspaceFolders ?? []) { - const uri = this.getOriginalResource(folder.uri); - + for (const context of contextStore.getForWorkspace()) { // If we have a saved context, but no longer have any changes, reset the context // We only do this on startup/reload to keep things consistent - if (contextStore.get(uri) !== undefined && !changeStore.hasChanges(folder.uri)) { - contextStore.delete(uri); + if (!changeStore.hasChanges(context.folderUri)) { + console.log('Clear context', context.folderUri.toString()); + contextStore.delete(context.folderUri); } } this.disposable = Disposable.from( - workspace.registerFileSystemProvider(scheme, this, { - isCaseSensitive: true, - }), + workspace.registerFileSystemProvider(scheme, this, { isCaseSensitive: true }), workspace.registerFileSearchProvider(scheme, this), workspace.registerTextSearchProvider(scheme, this), changeStore.onDidChange(e => { @@ -86,11 +82,11 @@ export class VirtualFS implements FileSystemProvider, FileSearchProvider, TextSe } private getOriginalResource(uri: Uri): Uri { - return uri.with({ scheme: this.originalScheme }); + return this.contextStore.getOriginalResource(uri); } - private getVirtualResource(uri: Uri): Uri { - return uri.with({ scheme: this.scheme }); + private getWorkspaceResource(uri: Uri): Uri { + return this.contextStore.getWorkspaceResource(uri); } //#region FileSystemProvider @@ -211,7 +207,7 @@ export class VirtualFS implements FileSystemProvider, FileSearchProvider, TextSe return this.fs.provideTextSearchResults( query, { ...options, folder: this.getOriginalResource(options.folder) }, - { report: (result: TextSearchResult) => progress.report({ ...result, uri: this.getVirtualResource(result.uri) }) }, + { report: (result: TextSearchResult) => progress.report({ ...result, uri: this.getWorkspaceResource(result.uri) }) }, token ); } diff --git a/extensions/github-browser/src/github/api.ts b/extensions/github-browser/src/github/api.ts index c90d874bfabfc..41eedc8fe39af 100644 --- a/extensions/github-browser/src/github/api.ts +++ b/extensions/github-browser/src/github/api.ts @@ -6,14 +6,16 @@ import { authentication, AuthenticationSession, Disposable, Event, EventEmitter, Range, Uri } from 'vscode'; import { graphql } from '@octokit/graphql'; import { Octokit } from '@octokit/rest'; -import { fromGitHubUri } from './fs'; import { ContextStore } from '../contextStore'; +import { fromGitHubUri } from './fs'; +import { isSha } from '../extension'; import { Iterables } from '../iterables'; -export const shaRegex = /^[0-9a-f]{40}$/; - export interface GitHubApiContext { - sha: string; + requestRef: string; + + branch: string; + sha: string | undefined; timestamp: number; } @@ -110,19 +112,12 @@ export class GitHubApi implements Disposable { } async commit(rootUri: Uri, message: string, operations: CommitOperation[]): Promise { - let { owner, repo, ref } = fromGitHubUri(rootUri); + const { owner, repo } = fromGitHubUri(rootUri); try { - if (ref === undefined || ref === 'HEAD') { - ref = await this.defaultBranchQuery(rootUri); - if (ref === undefined) { - throw new Error('Cannot commit — invalid ref'); - } - } - const context = await this.getContext(rootUri); if (context.sha === undefined) { - throw new Error('Cannot commit — invalid context'); + throw new Error(`Cannot commit to Uri(${rootUri.toString(true)}); Invalid context sha`); } const hasDeletes = operations.some(op => op.type === 'deleted'); @@ -204,14 +199,14 @@ export class GitHubApi implements Disposable { parents: [context.sha] }); - this.updateContext(rootUri, { sha: resp.data.sha, timestamp: Date.now() }); + this.updateContext(rootUri, { ...context, sha: resp.data.sha, timestamp: Date.now() }); // TODO@eamodio need to send a file change for any open files await github.git.updateRef({ owner: owner, repo: repo, - ref: `heads/${ref}`, + ref: `heads/${context.branch}`, sha: resp.data.sha }); @@ -256,7 +251,7 @@ export class GitHubApi implements Disposable { owner: owner, repo: repo, recursive: '1', - tree_sha: context?.sha ?? ref ?? 'HEAD', + tree_sha: context?.sha ?? ref, }); return Iterables.filterMap(resp.data.tree, p => p.type === 'blob' ? p.path : undefined); } catch (ex) { @@ -283,7 +278,7 @@ export class GitHubApi implements Disposable { }>(query, { owner: owner, repo: repo, - path: `${context.sha ?? ref ?? 'HEAD'}:${path}`, + path: `${context.sha ?? ref}:${path}`, }); return rsp?.repository?.object ?? undefined; } catch (ex) { @@ -295,7 +290,7 @@ export class GitHubApi implements Disposable { const { owner, repo, ref } = fromGitHubUri(uri); try { - if (ref === undefined || ref === 'HEAD') { + if (ref === 'HEAD') { const query = `query latest($owner: String!, $repo: String!) { repository(owner: $owner, name: $repo) { defaultBranchRef { @@ -322,6 +317,7 @@ export class GitHubApi implements Disposable { oid } } + } }`; const rsp = await this.gqlQuery<{ @@ -345,7 +341,7 @@ export class GitHubApi implements Disposable { const { owner, repo, ref } = fromGitHubUri(uri); // If we have a specific ref, don't try to search, because GitHub search only works against the default branch - if (ref === undefined) { + if (ref !== 'HEAD') { return { matches: [], limitHit: true }; } @@ -436,29 +432,46 @@ export class GitHubApi implements Disposable { private readonly rootUriToContextMap = new Map(); private async getContextCore(rootUri: Uri): Promise { - let context = this.rootUriToContextMap.get(rootUri.toString()); - if (context === undefined) { - const { ref } = fromGitHubUri(rootUri); - if (ref !== undefined && shaRegex.test(ref)) { - context = { sha: ref, timestamp: Date.now() }; - } else { - context = this.context.get(rootUri); - if (context?.sha === undefined) { - const sha = await this.latestCommitQuery(rootUri); - if (sha !== undefined) { - context = { sha: sha, timestamp: Date.now() }; - } else { - context = undefined; - } + const key = rootUri.toString(); + let context = this.rootUriToContextMap.get(key); + + // Check if we have a cached a context + if (context?.sha !== undefined) { + return context; + } + + // Check if we have a saved context + context = this.context.get(rootUri); + if (context?.sha !== undefined) { + this.rootUriToContextMap.set(key, context); + + return context; + } + + const { ref } = fromGitHubUri(rootUri); + + // If the requested ref looks like a sha, then use it + if (isSha(ref)) { + context = { requestRef: ref, branch: ref, sha: ref, timestamp: Date.now() }; + } else { + let branch; + if (ref === 'HEAD') { + branch = await this.defaultBranchQuery(rootUri); + if (branch === undefined) { + throw new Error(`Cannot get context for Uri(${rootUri.toString(true)}); unable to get default branch`); } + } else { + branch = ref; } - if (context !== undefined) { - this.updateContext(rootUri, context); - } + // Query for the latest sha for the give ref + const sha = await this.latestCommitQuery(rootUri); + context = { requestRef: ref, branch: branch, sha: sha, timestamp: Date.now() }; } - return context ?? { sha: rootUri.authority, timestamp: Date.now() }; + this.updateContext(rootUri, context); + + return context; } private updateContext(rootUri: Uri, context: GitHubApiContext) { diff --git a/extensions/github-browser/src/github/fs.ts b/extensions/github-browser/src/github/fs.ts index 4040cdcc7bafa..d0af10751c051 100644 --- a/extensions/github-browser/src/github/fs.ts +++ b/extensions/github-browser/src/github/fs.ts @@ -299,7 +299,7 @@ function typenameToFileType(typename: string | undefined | null) { } } -type RepoInfo = { owner: string; repo: string; path: string | undefined; ref?: string }; +type RepoInfo = { owner: string; repo: string; path: string | undefined; ref: string }; export function fromGitHubUri(uri: Uri): RepoInfo { const [, owner, repo, ...rest] = uri.path.split('/'); @@ -311,7 +311,7 @@ export function fromGitHubUri(uri: Uri): RepoInfo { ref = 'HEAD'; } } - return { owner: owner, repo: repo, path: rest.join('/'), ref: ref }; + return { owner: owner, repo: repo, path: rest.join('/'), ref: ref ?? 'HEAD' }; } function getHashCode(s: string): number { diff --git a/extensions/github-browser/src/scm.ts b/extensions/github-browser/src/scm.ts index 02666d3536e22..56671b46859c5 100644 --- a/extensions/github-browser/src/scm.ts +++ b/extensions/github-browser/src/scm.ts @@ -32,17 +32,15 @@ export class VirtualSCM implements Disposable { // TODO@eamodio listen for workspace folder changes for (const folder of workspace.workspaceFolders ?? []) { this.createScmProvider(folder.uri, folder.name); + + for (const operation of changeStore.getChanges(folder.uri)) { + this.update(folder.uri, operation.uri); + } } this.disposable = Disposable.from( changeStore.onDidChange(e => this.update(e.rootUri, e.uri)), ); - - for (const { uri } of workspace.workspaceFolders ?? []) { - for (const operation of changeStore.getChanges(uri)) { - this.update(uri, operation.uri); - } - } } dispose() { diff --git a/extensions/github-browser/src/statusbar.ts b/extensions/github-browser/src/statusbar.ts new file mode 100644 index 0000000000000..e5a049a8631ca --- /dev/null +++ b/extensions/github-browser/src/statusbar.ts @@ -0,0 +1,99 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +'use strict'; +import { Disposable, StatusBarAlignment, StatusBarItem, Uri, window, workspace } from 'vscode'; +import { ChangeStoreEvent, IChangeStore } from './changeStore'; +import { GitHubApiContext } from './github/api'; +import { isSha } from './extension'; +import { ContextStore, WorkspaceFolderContext } from './contextStore'; + +export class StatusBar implements Disposable { + private readonly disposable: Disposable; + + private readonly items = new Map(); + + constructor( + private readonly contextStore: ContextStore, + private readonly changeStore: IChangeStore + ) { + this.disposable = Disposable.from( + contextStore.onDidChange(this.onContextsChanged, this), + changeStore.onDidChange(this.onChanged, this) + ); + + for (const context of this.contextStore.getForWorkspace()) { + this.createOrUpdateStatusBarItem(context); + } + } + + dispose() { + this.disposable?.dispose(); + this.items.forEach(i => i.dispose()); + } + + private createOrUpdateStatusBarItem(wc: WorkspaceFolderContext) { + let item = this.items.get(wc.folderUri.toString()); + if (item === undefined) { + item = window.createStatusBarItem({ + id: `githubBrowser.branch:${wc.folderUri.toString()}`, + name: `GitHub Browser: ${wc.name}`, + alignment: StatusBarAlignment.Left, + priority: 1000 + }); + } + + if (isSha(wc.context.branch)) { + item.text = `$(git-commit) ${wc.context.branch.substr(0, 8)}`; + item.tooltip = `${wc.name} \u2022 ${wc.context.branch.substr(0, 8)}`; + } else { + item.text = `$(git-branch) ${wc.context.branch}`; + item.tooltip = `${wc.name} \u2022 ${wc.context.branch}${wc.context.sha ? ` @ ${wc.context.sha?.substr(0, 8)}` : ''}`; + } + + const hasChanges = this.changeStore.hasChanges(wc.folderUri); + if (hasChanges) { + item.text += '*'; + } + + item.show(); + + this.items.set(wc.folderUri.toString(), item); + } + + private onContextsChanged(uri: Uri) { + const folder = workspace.getWorkspaceFolder(this.contextStore.getWorkspaceResource(uri)); + if (folder === undefined) { + return; + } + + const context = this.contextStore.get(uri); + if (context === undefined) { + return; + } + + this.createOrUpdateStatusBarItem({ + context: context, + name: folder.name, + folderUri: folder.uri, + }); + } + + private onChanged(e: ChangeStoreEvent) { + const item = this.items.get(e.rootUri.toString()); + if (item !== undefined) { + const hasChanges = this.changeStore.hasChanges(e.rootUri); + if (hasChanges) { + if (!item.text.endsWith('*')) { + item.text += '*'; + } + } else { + if (item.text.endsWith('*')) { + item.text = item.text.substr(0, item.text.length - 1); + } + } + } + } +} From 051798aac4c4e9bfd502ab9e4ae6871c1d11f6c1 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Thu, 2 Jul 2020 10:17:45 +0200 Subject: [PATCH 66/93] web - fix performance measures --- src/vs/code/browser/workbench/workbench.ts | 3 +++ src/vs/code/electron-browser/workbench/workbench.js | 2 ++ 2 files changed, 5 insertions(+) diff --git a/src/vs/code/browser/workbench/workbench.ts b/src/vs/code/browser/workbench/workbench.ts index 556c03a03abff..4bd7368805409 100644 --- a/src/vs/code/browser/workbench/workbench.ts +++ b/src/vs/code/browser/workbench/workbench.ts @@ -277,6 +277,9 @@ class WorkspaceProvider implements IWorkspaceProvider { (function () { + // Mark start of workbench + performance.mark('workbench-start'); + // Find config by checking for DOM const configElement = document.getElementById('vscode-workbench-web-configuration'); const configElementAttribute = configElement ? configElement.getAttribute('data-settings') : undefined; diff --git a/src/vs/code/electron-browser/workbench/workbench.js b/src/vs/code/electron-browser/workbench/workbench.js index 8084d2d6e29b3..0ded47c0f4e80 100644 --- a/src/vs/code/electron-browser/workbench/workbench.js +++ b/src/vs/code/electron-browser/workbench/workbench.js @@ -54,6 +54,8 @@ bootstrapWindow.load([ 'vs/css!vs/workbench/workbench.desktop.main' ], function (workbench, configuration) { + + // Mark start of workbench perf.mark('didLoadWorkbenchMain'); performance.mark('workbench-start'); From 3d67b1b0efe5bf4640699d4784baad7f87ba2513 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Thu, 2 Jul 2020 10:42:13 +0200 Subject: [PATCH 67/93] scm ux, related to #101103 --- src/vs/workbench/contrib/scm/browser/media/scm.css | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/vs/workbench/contrib/scm/browser/media/scm.css b/src/vs/workbench/contrib/scm/browser/media/scm.css index c1cf75e6d262a..8cadb1e199e28 100644 --- a/src/vs/workbench/contrib/scm/browser/media/scm.css +++ b/src/vs/workbench/contrib/scm/browser/media/scm.css @@ -30,6 +30,10 @@ flex-flow: nowrap; } +.scm-view .scm-provider > .count { + display: none; +} + .scm-view .scm-provider > .label { display: flex; flex-shrink: 1; From dc7c90ad5d5717801476dbb1f804c66e0c9e4f98 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Thu, 2 Jul 2020 10:51:08 +0200 Subject: [PATCH 68/93] fixes #101572 --- .../contrib/scm/browser/scmViewPane.ts | 109 ++++++++++++++++-- 1 file changed, 97 insertions(+), 12 deletions(-) diff --git a/src/vs/workbench/contrib/scm/browser/scmViewPane.ts b/src/vs/workbench/contrib/scm/browser/scmViewPane.ts index 762cf40d91a01..3b91558f11a4b 100644 --- a/src/vs/workbench/contrib/scm/browser/scmViewPane.ts +++ b/src/vs/workbench/contrib/scm/browser/scmViewPane.ts @@ -76,7 +76,7 @@ import { ContextSubMenu } from 'vs/base/browser/contextmenu'; import { KeyCode } from 'vs/base/common/keyCodes'; import { DEFAULT_FONT_FAMILY } from 'vs/workbench/browser/style'; import { Command } from 'vs/editor/common/modes'; -import { renderCodicons } from 'vs/base/common/codicons'; +import { renderCodicons, Codicon } from 'vs/base/common/codicons'; import { ToolBar } from 'vs/base/browser/ui/toolbar/toolbar'; import { AnchorAlignment } from 'vs/base/browser/ui/contextview/contextview'; import { domEvent } from 'vs/base/browser/event'; @@ -831,6 +831,10 @@ class ViewModel { private readonly _onDidChangeMode = new Emitter(); readonly onDidChangeMode = this._onDidChangeMode.event; + private _onDidChangeRepositoryCollapseState = new Emitter(); + readonly onDidChangeRepositoryCollapseState: Event; + private visible: boolean = false; + get mode(): ViewModelMode { return this._mode; } set mode(mode: ViewModelMode) { this._mode = mode; @@ -867,7 +871,7 @@ class ViewModel { private disposables = new DisposableStore(); constructor( - private repositories: ISequence, + readonly repositories: ISequence, private tree: WorkbenchCompressibleObjectTree, private menus: SCMMenus, private inputRenderer: InputRenderer, @@ -875,12 +879,17 @@ class ViewModel { private _sortKey: ViewModelSortKey, @IEditorService protected editorService: IEditorService, @IConfigurationService protected configurationService: IConfigurationService, - ) { } + ) { + this.onDidChangeRepositoryCollapseState = Event.any( + this._onDidChangeRepositoryCollapseState.event, + Event.signal(Event.filter(this.tree.onDidChangeCollapseState, e => isSCMRepository(e.node.element))) + ); + } - private onDidSpliceRepositories({ start, deleteCount, toInsert }: ISplice): void { + private _onDidSpliceRepositories({ start, deleteCount, toInsert }: ISplice): void { const itemsToInsert = toInsert.map(repository => { const disposable = combinedDisposable( - repository.provider.groups.onDidSplice(splice => this.onDidSpliceGroups(item, splice)), + repository.provider.groups.onDidSplice(splice => this._onDidSpliceGroups(item, splice)), repository.input.onDidChangeVisibility(() => this.refresh(item)) ); const groupItems = repository.provider.groups.elements.map(group => this.createGroupItem(group)); @@ -902,7 +911,7 @@ class ViewModel { this.refresh(); } - private onDidSpliceGroups(item: IRepositoryItem, { start, deleteCount, toInsert }: ISplice): void { + private _onDidSpliceGroups(item: IRepositoryItem, { start, deleteCount, toInsert }: ISplice): void { const itemsToInsert: IGroupItem[] = toInsert.map(group => this.createGroupItem(group)); const itemsToDispose = item.groupItems.splice(start, deleteCount, ...itemsToInsert); @@ -918,7 +927,7 @@ class ViewModel { const resources: ISCMResource[] = [...group.elements]; const disposable = combinedDisposable( group.onDidChange(() => this.tree.refilter()), - group.onDidSplice(splice => this.onDidSpliceGroup(item, splice)) + group.onDidSplice(splice => this._onDidSpliceGroup(item, splice)) ); const item: IGroupItem = { element: group, resources, tree, disposable }; @@ -932,7 +941,7 @@ class ViewModel { return item; } - private onDidSpliceGroup(item: IGroupItem, { start, deleteCount, toInsert }: ISplice): void { + private _onDidSpliceGroup(item: IGroupItem, { start, deleteCount, toInsert }: ISplice): void { const before = item.resources.length; const deleted = item.resources.splice(start, deleteCount, ...toInsert); const after = item.resources.length; @@ -957,8 +966,8 @@ class ViewModel { setVisible(visible: boolean): void { if (visible) { this.visibilityDisposables = new DisposableStore(); - this.repositories.onDidSplice(this.onDidSpliceRepositories, this, this.visibilityDisposables); - this.onDidSpliceRepositories({ start: 0, deleteCount: 0, toInsert: this.repositories.elements }); + this.repositories.onDidSplice(this._onDidSpliceRepositories, this, this.visibilityDisposables); + this._onDidSpliceRepositories({ start: 0, deleteCount: 0, toInsert: this.repositories.elements }); this.repositoryCollapseStates = undefined; if (typeof this.scrollTop === 'number') { @@ -978,9 +987,12 @@ class ViewModel { } this.visibilityDisposables.dispose(); - this.onDidSpliceRepositories({ start: 0, deleteCount: this.items.length, toInsert: [] }); + this._onDidSpliceRepositories({ start: 0, deleteCount: this.items.length, toInsert: [] }); this.scrollTop = this.tree.scrollTop; } + + this.visible = visible; + this._onDidChangeRepositoryCollapseState.fire(); } private refresh(item?: IRepositoryItem | IGroupItem): void { @@ -991,6 +1003,8 @@ class ViewModel { } else { this.tree.setChildren(null, this.items.map(item => this.render(item))); } + + this._onDidChangeRepositoryCollapseState.fire(); } private render(item: IRepositoryItem | IGroupItem): ICompressedTreeElement { @@ -1082,6 +1096,10 @@ class ViewModel { } getViewSecondaryActions(): IAction[] { + if (this.repositories.elements.length === 0) { + return []; + } + const viewAction = new SCMViewSubMenuAction(this); if (this.repositories.elements.length !== 1) { @@ -1106,6 +1124,38 @@ class ViewModel { return this.repositories.elements[0].provider; } + collapseAllProviders(): void { + for (const repository of this.repositories.elements) { + if (this.tree.isCollapsible(repository)) { + this.tree.collapse(repository); + } + } + } + + expandAllProviders(): void { + for (const repository of this.repositories.elements) { + if (this.tree.isCollapsible(repository)) { + this.tree.expand(repository); + } + } + } + + isAnyProviderCollapsible(): boolean { + if (!this.visible || this.repositories.elements.length === 1) { + return false; + } + + return this.repositories.elements.some(r => this.tree.hasElement(r) && this.tree.isCollapsible(r)); + } + + areAllProvidersCollapsed(): boolean { + if (!this.visible || this.repositories.elements.length === 1) { + return false; + } + + return this.repositories.elements.every(r => this.tree.hasElement(r) && (!this.tree.isCollapsible(r) || this.tree.isCollapsed(r))); + } + dispose(): void { this.visibilityDisposables.dispose(); this.disposables.dispose(); @@ -1490,6 +1540,34 @@ class SCMInputWidget extends Disposable { } } +class SCMCollapseAction extends Action { + + private allCollapsed = false; + + constructor(private viewModel: ViewModel) { + super('scm.collapse', undefined, undefined, true); + this._register(viewModel.onDidChangeRepositoryCollapseState(this.update, this)); + this.update(); + } + + async run(): Promise { + if (this.allCollapsed) { + this.viewModel.expandAllProviders(); + } else { + this.viewModel.collapseAllProviders(); + } + } + + private update(): void { + const isAnyProviderCollapsible = this.viewModel.isAnyProviderCollapsible(); + + this.enabled = isAnyProviderCollapsible; + this.allCollapsed = isAnyProviderCollapsible && this.viewModel.areAllProvidersCollapsed(); + this.label = this.allCollapsed ? localize('expand all', "Expand All Providers") : localize('collapse all', "Collapse All Providers"); + this.class = this.allCollapsed ? Codicon.expandAll.classNames : Codicon.collapseAll.classNames; + } +} + export class SCMViewPane extends ViewPane { private _onDidLayout = new Emitter(); @@ -1660,7 +1738,14 @@ export class SCMViewPane extends ViewPane { return []; } - return this.viewModel.getViewActions(); + if (this.viewModel.repositories.elements.length < 2) { + return this.viewModel.getViewActions(); + } + + return [ + new SCMCollapseAction(this.viewModel), + ...this.viewModel.getViewActions() + ]; } getSecondaryActions(): IAction[] { From 8053b229182f744af03fc5e365579fd3bb96cbd6 Mon Sep 17 00:00:00 2001 From: isidor Date: Thu, 2 Jul 2020 10:57:26 +0200 Subject: [PATCH 69/93] fixes #101554 --- src/vs/workbench/api/common/extHostStatusBar.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/vs/workbench/api/common/extHostStatusBar.ts b/src/vs/workbench/api/common/extHostStatusBar.ts index bc2c6fa2d0b1a..edbaec0f60ab5 100644 --- a/src/vs/workbench/api/common/extHostStatusBar.ts +++ b/src/vs/workbench/api/common/extHostStatusBar.ts @@ -117,6 +117,11 @@ export class ExtHostStatusBarEntry implements vscode.StatusBarItem { this.update(); } + public set accessibilityInformation(accessibilityInformation: vscode.AccessibilityInformation | undefined) { + this._accessibilityInformation = accessibilityInformation; + this.update(); + } + public show(): void { this._visible = true; this.update(); From cf6b10a88a9531f6ff2d79730bc2b23ff0f4f29f Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Thu, 2 Jul 2020 11:26:43 +0200 Subject: [PATCH 70/93] add verification notebook --- .vscode/notebooks/verification.github-issues | 44 ++++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 .vscode/notebooks/verification.github-issues diff --git a/.vscode/notebooks/verification.github-issues b/.vscode/notebooks/verification.github-issues new file mode 100644 index 0000000000000..9d757447a214e --- /dev/null +++ b/.vscode/notebooks/verification.github-issues @@ -0,0 +1,44 @@ +[ + { + "kind": 1, + "language": "markdown", + "value": "### Bug Verification Queries\n\nBefore shipping we want to verify _all_ bugs. That means when a bug is fixed we check that the fix actually works. It's always best to start with bugs that you have filed and the proceed with bugs that have been filed from users outside the development team. ", + "editable": true + }, + { + "kind": 1, + "language": "markdown", + "value": "**Config**: update list of `repos` and the `milestone`", + "editable": true + }, + { + "kind": 2, + "language": "github-issues", + "value": "$repos=repo:microsoft/vscode repo:microsoft/vscode-internalbacklog repo:microsoft/vscode-remote-release repo:microsoft/vscode-js-debug repo:microsoft/vscode-pull-request-github repo:microsoft/vscode-github-issue-notebooks \n$milestone=milestone:\"June 2020\"", + "editable": true + }, + { + "kind": 1, + "language": "markdown", + "value": "### Bugs You Filed", + "editable": true + }, + { + "kind": 2, + "language": "github-issues", + "value": "$repos $milestone is:closed -assignee:@me label:bug -label:verified author:@me", + "editable": false + }, + { + "kind": 1, + "language": "markdown", + "value": "### Bugs From Outside", + "editable": true + }, + { + "kind": 2, + "language": "github-issues", + "value": "$repos $milestone is:closed -assignee:@me label:bug -label:verified -author:@me -assignee:@me label:bug -label:verified -author:@me -author:aeschli -author:alexdima -author:alexr00 -author:bpasero -author:chrisdias -author:chrmarti -author:connor4312 -author:dbaeumer -author:deepak1556 -author:eamodio -author:egamma -author:gregvanl -author:isidorn -author:JacksonKearl -author:joaomoreno -author:jrieken -author:lramos15 -author:lszomoru -author:misolori -author:mjbvz -author:rebornix -author:RMacfarlane -author:roblourens -author:sana-ajani -author:sandy081 -author:sbatten -author:Tyriar -author:weinand", + "editable": false + } +] \ No newline at end of file From 819bc7363d1354755be529e1f072d193dc0c30e8 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Thu, 2 Jul 2020 11:28:24 +0200 Subject: [PATCH 71/93] tweaks --- .vscode/notebooks/verification.github-issues | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.vscode/notebooks/verification.github-issues b/.vscode/notebooks/verification.github-issues index 9d757447a214e..7e26dd87005b5 100644 --- a/.vscode/notebooks/verification.github-issues +++ b/.vscode/notebooks/verification.github-issues @@ -8,7 +8,7 @@ { "kind": 1, "language": "markdown", - "value": "**Config**: update list of `repos` and the `milestone`", + "value": "#### Config: update list of `repos` and the `milestone`", "editable": true }, { From a301dc553bede42fe03a9d174a41c8d7816fbaf6 Mon Sep 17 00:00:00 2001 From: isidor Date: Thu, 2 Jul 2020 11:37:27 +0200 Subject: [PATCH 72/93] change noCompress -> compress and make default to not compress sessions in call stack #101429 --- src/vs/vscode.proposed.d.ts | 6 +++--- .../api/browser/mainThreadDebugService.ts | 2 +- src/vs/workbench/api/common/extHost.protocol.ts | 2 +- .../workbench/api/common/extHostDebugService.ts | 2 +- .../contrib/debug/browser/callStackView.ts | 15 +++++++++++++-- .../contrib/debug/browser/debugSession.ts | 4 ++-- src/vs/workbench/contrib/debug/common/debug.ts | 4 ++-- .../contrib/debug/test/common/mockDebug.ts | 2 +- 8 files changed, 24 insertions(+), 13 deletions(-) diff --git a/src/vs/vscode.proposed.d.ts b/src/vs/vscode.proposed.d.ts index 40c73e63abcd4..0cc285c607151 100644 --- a/src/vs/vscode.proposed.d.ts +++ b/src/vs/vscode.proposed.d.ts @@ -831,10 +831,10 @@ declare module 'vscode' { /** * Controls if the debug session's parent session is shown in the CALL STACK view even if it has only a single child. - * By default, debug sessions with a single child are hidden in the CALL STACK view to make the tree more compact. - * If noCompact is true, then the debug session will never hide its parent. + * By default, the debug session will never hide its parent. + * If compact is true, debug sessions with a single child are hidden in the CALL STACK view to make the tree more compact. */ - noCompact?: boolean; + compact?: boolean; } // deprecated debug API diff --git a/src/vs/workbench/api/browser/mainThreadDebugService.ts b/src/vs/workbench/api/browser/mainThreadDebugService.ts index eada65f9f62c7..1ddadf87184a0 100644 --- a/src/vs/workbench/api/browser/mainThreadDebugService.ts +++ b/src/vs/workbench/api/browser/mainThreadDebugService.ts @@ -232,7 +232,7 @@ export class MainThreadDebugService implements MainThreadDebugServiceShape, IDeb noDebug: options.noDebug, parentSession: this.getSession(options.parentSessionID), repl: options.repl, - noCompact: options.noCompact + compact: options.compact }; return this.debugService.startDebugging(launch, nameOrConfig, debugOptions).then(success => { return success; diff --git a/src/vs/workbench/api/common/extHost.protocol.ts b/src/vs/workbench/api/common/extHost.protocol.ts index 23497dc06b29c..0490360f285c6 100644 --- a/src/vs/workbench/api/common/extHost.protocol.ts +++ b/src/vs/workbench/api/common/extHost.protocol.ts @@ -858,7 +858,7 @@ export interface IStartDebuggingOptions { parentSessionID?: DebugSessionUUID; repl?: IDebugSessionReplMode; noDebug?: boolean; - noCompact?: boolean; + compact?: boolean; } export interface MainThreadDebugServiceShape extends IDisposable { diff --git a/src/vs/workbench/api/common/extHostDebugService.ts b/src/vs/workbench/api/common/extHostDebugService.ts index f9b766a8106f1..6fc0dc2bdc1c1 100644 --- a/src/vs/workbench/api/common/extHostDebugService.ts +++ b/src/vs/workbench/api/common/extHostDebugService.ts @@ -297,7 +297,7 @@ export abstract class ExtHostDebugServiceBase implements IExtHostDebugService, E parentSessionID: options.parentSession ? options.parentSession.id : undefined, repl: options.consoleMode === DebugConsoleMode.MergeWithParent ? 'mergeWithParent' : 'separate', noDebug: options.noDebug, - noCompact: options.noCompact + compact: options.compact }); } diff --git a/src/vs/workbench/contrib/debug/browser/callStackView.ts b/src/vs/workbench/contrib/debug/browser/callStackView.ts index 7e27b4b03d550..9fb005a0a7947 100644 --- a/src/vs/workbench/contrib/debug/browser/callStackView.ts +++ b/src/vs/workbench/contrib/debug/browser/callStackView.ts @@ -217,7 +217,7 @@ export class CallStackView extends ViewPane { this.dataSource = new CallStackDataSource(this.debugService); const sessionsRenderer = this.instantiationService.createInstance(SessionsRenderer, this.menu); - this.tree = >this.instantiationService.createInstance(WorkbenchCompressibleAsyncDataTree, 'CallStackView', treeContainer, new CallStackDelegate(), new CallStackCompressionDelegate(), [ + this.tree = >this.instantiationService.createInstance(WorkbenchCompressibleAsyncDataTree, 'CallStackView', treeContainer, new CallStackDelegate(), new CallStackCompressionDelegate(this.debugService), [ sessionsRenderer, new ThreadsRenderer(this.instantiationService), this.instantiationService.createInstance(StackFramesRenderer), @@ -1104,9 +1104,20 @@ class ContinueAction extends Action { } class CallStackCompressionDelegate implements ITreeCompressionDelegate { + + constructor(private readonly debugService: IDebugService) { } + isIncompressible(stat: CallStackItem): boolean { if (isDebugSession(stat)) { - return stat.noCompact; + if (stat.compact) { + return false; + } + const sessions = this.debugService.getModel().getSessions(); + if (sessions.some(s => s.parentSession === stat && s.compact)) { + return false; + } + + return true; } return true; diff --git a/src/vs/workbench/contrib/debug/browser/debugSession.ts b/src/vs/workbench/contrib/debug/browser/debugSession.ts index 7272b2333cc06..f6d4e37cbb8c0 100644 --- a/src/vs/workbench/contrib/debug/browser/debugSession.ts +++ b/src/vs/workbench/contrib/debug/browser/debugSession.ts @@ -129,8 +129,8 @@ export class DebugSession implements IDebugSession { return this._options.parentSession; } - get noCompact(): boolean { - return !!this._options.noCompact; + get compact(): boolean { + return !!this._options.compact; } setConfiguration(configuration: { resolved: IConfig, unresolved: IConfig | undefined }) { diff --git a/src/vs/workbench/contrib/debug/common/debug.ts b/src/vs/workbench/contrib/debug/common/debug.ts index 7692955d9ed91..84adc75d705a6 100644 --- a/src/vs/workbench/contrib/debug/common/debug.ts +++ b/src/vs/workbench/contrib/debug/common/debug.ts @@ -157,7 +157,7 @@ export interface IDebugSessionOptions { parentSession?: IDebugSession; repl?: IDebugSessionReplMode; compoundRoot?: DebugCompoundRoot; - noCompact?: boolean; + compact?: boolean; } export interface IDebugSession extends ITreeElement { @@ -168,7 +168,7 @@ export interface IDebugSession extends ITreeElement { readonly root: IWorkspaceFolder | undefined; readonly parentSession: IDebugSession | undefined; readonly subId: string | undefined; - readonly noCompact: boolean; + readonly compact: boolean; setSubId(subId: string | undefined): void; diff --git a/src/vs/workbench/contrib/debug/test/common/mockDebug.ts b/src/vs/workbench/contrib/debug/test/common/mockDebug.ts index 6576e21e88ea4..1b3b1f2beba14 100644 --- a/src/vs/workbench/contrib/debug/test/common/mockDebug.ts +++ b/src/vs/workbench/contrib/debug/test/common/mockDebug.ts @@ -157,7 +157,7 @@ export class MockSession implements IDebugSession { subId: string | undefined; - get noCompact(): boolean { + get compact(): boolean { return false; } From 13885429b79dc02db69c7f30dfb597db190e1b2e Mon Sep 17 00:00:00 2001 From: isidor Date: Thu, 2 Jul 2020 11:43:59 +0200 Subject: [PATCH 73/93] compacted debug sessions should show name of child and not of parent fixes #101429 --- src/vs/workbench/contrib/debug/browser/callStackView.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/vs/workbench/contrib/debug/browser/callStackView.ts b/src/vs/workbench/contrib/debug/browser/callStackView.ts index 9fb005a0a7947..13e0d80e91af5 100644 --- a/src/vs/workbench/contrib/debug/browser/callStackView.ts +++ b/src/vs/workbench/contrib/debug/browser/callStackView.ts @@ -521,18 +521,18 @@ class SessionsRenderer implements ICompressibleTreeRenderer, _: number, data: ISessionTemplateData): void { - this.doRenderElement(element.element, element.element.getLabel(), createMatches(element.filterData), data); + this.doRenderElement(element.element, createMatches(element.filterData), data); } renderCompressedElements(node: ITreeNode, FuzzyScore>, index: number, templateData: ISessionTemplateData, height: number | undefined): void { const lastElement = node.element.elements[node.element.elements.length - 1]; const matches = createMatches(node.filterData); - this.doRenderElement(lastElement, node.element.elements[0].getLabel(), matches, templateData); + this.doRenderElement(lastElement, matches, templateData); } - private doRenderElement(session: IDebugSession, label: string, matches: IMatch[], data: ISessionTemplateData): void { + private doRenderElement(session: IDebugSession, matches: IMatch[], data: ISessionTemplateData): void { data.session.title = nls.localize({ key: 'session', comment: ['Session is a noun'] }, "Session"); - data.label.set(label, matches); + data.label.set(session.getLabel(), matches); const thread = session.getAllThreads().find(t => t.stopped); const setActionBar = () => { From 7e9c8f481499cc259e4ca0e72ce6bb27708fffc7 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Thu, 2 Jul 2020 11:58:22 +0200 Subject: [PATCH 74/93] exclude duplicates from verification --- .vscode/notebooks/verification.github-issues | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.vscode/notebooks/verification.github-issues b/.vscode/notebooks/verification.github-issues index 7e26dd87005b5..ba41571836b7e 100644 --- a/.vscode/notebooks/verification.github-issues +++ b/.vscode/notebooks/verification.github-issues @@ -26,7 +26,7 @@ { "kind": 2, "language": "github-issues", - "value": "$repos $milestone is:closed -assignee:@me label:bug -label:verified author:@me", + "value": "$repos $milestone is:closed -assignee:@me label:bug -label:verified -label:*duplicate author:@me", "editable": false }, { @@ -38,7 +38,7 @@ { "kind": 2, "language": "github-issues", - "value": "$repos $milestone is:closed -assignee:@me label:bug -label:verified -author:@me -assignee:@me label:bug -label:verified -author:@me -author:aeschli -author:alexdima -author:alexr00 -author:bpasero -author:chrisdias -author:chrmarti -author:connor4312 -author:dbaeumer -author:deepak1556 -author:eamodio -author:egamma -author:gregvanl -author:isidorn -author:JacksonKearl -author:joaomoreno -author:jrieken -author:lramos15 -author:lszomoru -author:misolori -author:mjbvz -author:rebornix -author:RMacfarlane -author:roblourens -author:sana-ajani -author:sandy081 -author:sbatten -author:Tyriar -author:weinand", + "value": "$repos $milestone is:closed -assignee:@me label:bug -label:verified -label:*duplicate -author:@me -assignee:@me label:bug -label:verified -author:@me -author:aeschli -author:alexdima -author:alexr00 -author:bpasero -author:chrisdias -author:chrmarti -author:connor4312 -author:dbaeumer -author:deepak1556 -author:eamodio -author:egamma -author:gregvanl -author:isidorn -author:JacksonKearl -author:joaomoreno -author:jrieken -author:lramos15 -author:lszomoru -author:misolori -author:mjbvz -author:rebornix -author:RMacfarlane -author:roblourens -author:sana-ajani -author:sandy081 -author:sbatten -author:Tyriar -author:weinand", "editable": false } ] \ No newline at end of file From b086502c8d844aa010898a96f006ff8060a092cf Mon Sep 17 00:00:00 2001 From: Alex Ross Date: Thu, 2 Jul 2020 12:09:55 +0200 Subject: [PATCH 75/93] Properly convert markdown for tree hovers Fixes https://github.com/microsoft/vscode-pull-request-github/issues/1945 --- src/vs/workbench/api/common/extHostTreeViews.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/api/common/extHostTreeViews.ts b/src/vs/workbench/api/common/extHostTreeViews.ts index 2b376fb1bfc5a..ea8c42d7f1be1 100644 --- a/src/vs/workbench/api/common/extHostTreeViews.ts +++ b/src/vs/workbench/api/common/extHostTreeViews.ts @@ -360,7 +360,7 @@ class ExtHostTreeView extends Disposable { if (node) { const resolve = await this.dataProvider.resolveTreeItem(element, node.extensionItem); // Resolvable elements. Currently only tooltip. - node.item.tooltip = resolve.tooltip; + node.item.tooltip = this.getTooltip(resolve.tooltip); return node.item; } } From 8d4ec36ba63fa8aa067c0173070c05e654820862 Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Thu, 2 Jul 2020 12:11:44 +0200 Subject: [PATCH 76/93] JSON doc needs to escape icon reference Fixes #101512 --- src/vs/workbench/api/common/menusExtensionPoint.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/api/common/menusExtensionPoint.ts b/src/vs/workbench/api/common/menusExtensionPoint.ts index b1ac5aa3af804..9e38664bafc97 100644 --- a/src/vs/workbench/api/common/menusExtensionPoint.ts +++ b/src/vs/workbench/api/common/menusExtensionPoint.ts @@ -338,7 +338,7 @@ namespace schema { type: 'string' }, icon: { - description: localize('vscode.extension.contributes.commandType.icon', '(Optional) Icon which is used to represent the command in the UI. Either a file path, an object with file paths for dark and light themes, or a theme icon references, like `$(zap)`'), + description: localize('vscode.extension.contributes.commandType.icon', '(Optional) Icon which is used to represent the command in the UI. Either a file path, an object with file paths for dark and light themes, or a theme icon references, like `\\$(zap)`'), anyOf: [{ type: 'string' }, From 7b5d3adb33325b59a751975b5402837406ed31e3 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Thu, 2 Jul 2020 14:11:26 +0200 Subject: [PATCH 77/93] Comments for #100941 --- .../extensions/electron-browser/runtimeExtensionsEditor.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/extensions/electron-browser/runtimeExtensionsEditor.ts b/src/vs/workbench/contrib/extensions/electron-browser/runtimeExtensionsEditor.ts index 9a08146497ada..219f14298f0c2 100644 --- a/src/vs/workbench/contrib/extensions/electron-browser/runtimeExtensionsEditor.ts +++ b/src/vs/workbench/contrib/extensions/electron-browser/runtimeExtensionsEditor.ts @@ -374,7 +374,12 @@ export class RuntimeExtensionsEditor extends BaseEditor { ] }, "Activated by {1} because searching for {0} took too long", glob, activationId); } else if (activationEvent === 'onStartupFinished') { - title = nls.localize('startupFinishedActivation', "Activated by {0} after start-up finished", activationId); + title = nls.localize({ + key: 'startupFinishedActivation', + comment: [ + 'This refers to an extension. {0} will be an activation event.' + ] + }, "Activated by {0} after start-up finished", activationId); } else if (/^onLanguage:/.test(activationEvent)) { let language = activationEvent.substr('onLanguage:'.length); title = nls.localize('languageActivation', "Activated by {1} because you opened a {0} file", language, activationId); From a564c958cdf0c8340f53bd87343f08ce500e3cdb Mon Sep 17 00:00:00 2001 From: kieferrm Date: Thu, 2 Jul 2020 13:57:37 +0000 Subject: [PATCH 78/93] update distro --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index f9e642482a24c..63808590a9a66 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "code-oss-dev", "version": "1.47.0", - "distro": "246a61c6669daa9d9441c782b42579c61866cfa8", + "distro": "805dcb641373964d569e29bb3ff662f8d3cda469", "author": { "name": "Microsoft Corporation" }, From 5330886338d30eb4e6679de092f24cd5f107a429 Mon Sep 17 00:00:00 2001 From: Miguel Solorio Date: Thu, 2 Jul 2020 10:56:02 -0700 Subject: [PATCH 79/93] Reduce whitespace in notebook cells (refs #101600) --- .../contrib/notebook/browser/constants.ts | 12 +++++----- .../notebook/browser/media/notebook.css | 24 +++++++++---------- .../notebook/browser/notebookEditorWidget.ts | 1 - 3 files changed, 17 insertions(+), 20 deletions(-) diff --git a/src/vs/workbench/contrib/notebook/browser/constants.ts b/src/vs/workbench/contrib/notebook/browser/constants.ts index 08797d89249e2..e4b14689ee76d 100644 --- a/src/vs/workbench/contrib/notebook/browser/constants.ts +++ b/src/vs/workbench/contrib/notebook/browser/constants.ts @@ -8,17 +8,17 @@ export const SCROLLABLE_ELEMENT_PADDING_TOP = 20; // Cell sizing related -export const CELL_MARGIN = 24; -export const CELL_RUN_GUTTER = 32; -export const CODE_CELL_LEFT_MARGIN = 45; +export const CELL_MARGIN = 16; +export const CELL_RUN_GUTTER = 28; +export const CODE_CELL_LEFT_MARGIN = 44; export const EDITOR_TOOLBAR_HEIGHT = 0; -export const BOTTOM_CELL_TOOLBAR_HEIGHT = 32; +export const BOTTOM_CELL_TOOLBAR_HEIGHT = 28; export const CELL_STATUSBAR_HEIGHT = 22; // Margin above editor -export const EDITOR_TOP_MARGIN = 8; -export const CELL_BOTTOM_MARGIN = 8; +export const EDITOR_TOP_MARGIN = 6; +export const CELL_BOTTOM_MARGIN = 6; // Top and bottom padding inside the monaco editor in a cell, which are included in `cell.editorHeight` export const EDITOR_TOP_PADDING = 12; diff --git a/src/vs/workbench/contrib/notebook/browser/media/notebook.css b/src/vs/workbench/contrib/notebook/browser/media/notebook.css index de47d0d95e48b..793cd1294a897 100644 --- a/src/vs/workbench/contrib/notebook/browser/media/notebook.css +++ b/src/vs/workbench/contrib/notebook/browser/media/notebook.css @@ -356,7 +356,7 @@ .monaco-workbench .notebookOverlay > .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .monaco-list-row .cell .run-button-container .monaco-toolbar .codicon { margin: 0; - padding: 0 4px; + padding-right: 4px; } .monaco-workbench .notebookOverlay > .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .monaco-list-row .cell .run-button-container .monaco-toolbar .actions-container { @@ -623,7 +623,7 @@ /* Adjust margin of first item in markdown cell */ .monaco-workbench .notebookOverlay .cell.markdown div *:first-child { - margin-top: 4px; + margin-top: 0px; } /* h1 tags don't need top margin */ @@ -632,18 +632,15 @@ } /* Removes bottom margin when only one item exists in markdown cell */ -.monaco-workbench .notebookOverlay .cell.markdown div h1:only-child, -.monaco-workbench .notebookOverlay .cell.markdown div h2:only-child, -.monaco-workbench .notebookOverlay .cell.markdown div h3:only-child, -.monaco-workbench .notebookOverlay .cell.markdown div h1:last-child, -.monaco-workbench .notebookOverlay .cell.markdown div h2:last-child, -.monaco-workbench .notebookOverlay .cell.markdown div h3:last-child { +.monaco-workbench .notebookOverlay .cell.markdown div *:only-child, +.monaco-workbench .notebookOverlay .cell.markdown div *:last-child { margin-bottom: 0; + padding-bottom: 0; } /* makes all markdown cells consistent */ .monaco-workbench .notebookOverlay .cell.markdown div { - min-height: 32px; + min-height: 24px; } .monaco-workbench .notebookOverlay .cell.markdown table { @@ -711,15 +708,16 @@ .monaco-workbench .notebookOverlay > .cell-list-container .notebook-folding-indicator { position: absolute; - top: 11px; - left: 0px; + top: 0; + left: 0; right: 0; + height: 100%; } .monaco-workbench .notebookOverlay > .cell-list-container .notebook-folding-indicator .codicon { visibility: visible; - padding: 4px; - width: calc(100% - 30px); + padding: 8px 4px 0; + width: calc(100% - 32px); } /** Theming */ diff --git a/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts b/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts index de406748cb401..25c17890289ec 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts @@ -1566,7 +1566,6 @@ registerThemingParticipant((theme, collector) => { collector.addRule(`.notebookOverlay .output { width: calc(100% - ${CODE_CELL_LEFT_MARGIN + CELL_RUN_GUTTER + CELL_MARGIN}px); }`); collector.addRule(`.notebookOverlay .cell-bottom-toolbar-container { width: calc(100% - ${CELL_MARGIN * 2 + CELL_RUN_GUTTER}px); margin: 0px ${CELL_MARGIN}px 0px ${CELL_MARGIN + CELL_RUN_GUTTER}px; }`); - collector.addRule(`.notebookOverlay .markdown-cell-row .cell .cell-editor-part { margin-left: ${CELL_RUN_GUTTER}px; }`); collector.addRule(`.notebookOverlay .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .monaco-list-row > div.cell.markdown { padding-left: ${CELL_RUN_GUTTER}px; }`); collector.addRule(`.notebookOverlay .cell .run-button-container { width: ${CELL_RUN_GUTTER}px; }`); collector.addRule(`.notebookOverlay .cell-drag-image .cell-editor-container > div { padding: ${EDITOR_TOP_PADDING}px 16px ${EDITOR_BOTTOM_PADDING}px 16px; }`); From a18eb1833f6b4b38fb5e43ea85ae27fcf3e59c96 Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Thu, 2 Jul 2020 11:12:03 -0700 Subject: [PATCH 80/93] Bump node-debug --- product.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/product.json b/product.json index 2d4bdaa2d5fe2..3986c1e913007 100644 --- a/product.json +++ b/product.json @@ -30,7 +30,7 @@ "builtInExtensions": [ { "name": "ms-vscode.node-debug", - "version": "1.44.6", + "version": "1.44.7", "repo": "https://github.com/Microsoft/vscode-node-debug", "metadata": { "id": "b6ded8fb-a0a0-4c1c-acbd-ab2a3bc995a6", From 6074f92d266571c180627dedbfd2525745d037b0 Mon Sep 17 00:00:00 2001 From: Miguel Solorio Date: Thu, 2 Jul 2020 11:14:42 -0700 Subject: [PATCH 81/93] Update notebook cell color token descriptions (fixes #98984) --- .../contrib/notebook/browser/notebookEditorWidget.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts b/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts index 25c17890289ec..0ab698dd6f7dd 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts @@ -1347,31 +1347,31 @@ export const CELL_TOOLBAR_SEPERATOR = registerColor('notebook.cellToolbarSeperat dark: Color.fromHex('#808080').transparent(0.35), light: Color.fromHex('#808080').transparent(0.35), hc: contrastBorder -}, nls.localize('cellToolbarSeperator', "The color of the seperator in the cell bottom toolbar")); +}, nls.localize('notebook.cellToolbarSeperator', "The color of the seperator in the cell bottom toolbar")); export const focusedCellBackground = registerColor('notebook.focusedCellBackground', { dark: transparent(PANEL_BORDER, .4), light: transparent(listFocusBackground, .4), hc: null -}, nls.localize('focusedCellBackground', "The background color of focused cells.")); +}, nls.localize('focusedCellBackground', "The background color of a cell when the cell is focused.")); export const cellHoverBackground = registerColor('notebook.cellHoverBackground', { dark: transparent(focusedCellBackground, .5), light: transparent(focusedCellBackground, .7), hc: null -}, nls.localize('notebook.cellHoverBackground', "The background color of hovered cells.")); +}, nls.localize('notebook.cellHoverBackground', "The background color of a cell when the cell is hovered.")); export const focusedCellBorder = registerColor('notebook.focusedCellBorder', { dark: Color.white.transparent(0.12), light: Color.black.transparent(0.12), hc: focusBorder -}, nls.localize('notebook.focusedCellBorder', "The color of focused cells.")); +}, nls.localize('notebook.focusedCellBorder', "The color of the cell's top and bottom border when the cell is focused.")); export const focusedCellShadow = registerColor('notebook.focusedCellShadow', { dark: transparent(widgetShadow, 0.6), light: transparent(widgetShadow, 0.4), hc: Color.transparent -}, nls.localize('notebook.focusedCellShadow', "The color of the shadow on the focused or hovered cell")); +}, nls.localize('notebook.focusedCellShadow', "The color of the cell shadow when cells are focused.")); export const cellStatusBarItemHover = registerColor('notebook.cellStatusBarItemHoverBackground', { light: new Color(new RGBA(0, 0, 0, 0.08)), From bc74f92c929c42566c270c0dd8ef856ea15a377a Mon Sep 17 00:00:00 2001 From: SteVen Batten Date: Thu, 2 Jul 2020 11:35:31 -0700 Subject: [PATCH 82/93] fixes #101592 --- src/vs/workbench/browser/parts/compositeBar.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/browser/parts/compositeBar.ts b/src/vs/workbench/browser/parts/compositeBar.ts index ae1c9de47437d..9893b5af2ba66 100644 --- a/src/vs/workbench/browser/parts/compositeBar.ts +++ b/src/vs/workbench/browser/parts/compositeBar.ts @@ -418,7 +418,7 @@ export class CompositeBar extends Widget implements ICompositeBar { // Case: we closed the last visible composite // Solv: we hide the part - else if (this.visibleComposites.length === 1) { + else if (this.visibleComposites.length === 0) { this.options.hidePart(); } From 800caa0f7fcbfabc229f35878ff5d8cf848eb34c Mon Sep 17 00:00:00 2001 From: Connor Peet Date: Thu, 2 Jul 2020 11:37:04 -0700 Subject: [PATCH 83/93] debug: close whole vscode 'browser' when ending sessions Fixes https://github.com/microsoft/vscode-js-debug/issues/554 --- .vscode/launch.json | 1 + 1 file changed, 1 insertion(+) diff --git a/.vscode/launch.json b/.vscode/launch.json index 7454d166f96f6..a46026d692bfb 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -200,6 +200,7 @@ "env": { "VSCODE_EXTHOST_WILL_SEND_SOCKET": null }, + "cleanUp": "wholeBrowser", "breakOnLoad": false, "urlFilter": "*workbench.html*", "runtimeArgs": [ From 842537285e8ad33e0253d248a9a2516942947929 Mon Sep 17 00:00:00 2001 From: Eric Amodio Date: Thu, 2 Jul 2020 15:08:20 -0400 Subject: [PATCH 84/93] =?UTF-8?q?Makes=20=E2=9C=94=20commit=20button=20wor?= =?UTF-8?q?k?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- extensions/github-browser/src/scm.ts | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/extensions/github-browser/src/scm.ts b/extensions/github-browser/src/scm.ts index 56671b46859c5..7a8e4292f2225 100644 --- a/extensions/github-browser/src/scm.ts +++ b/extensions/github-browser/src/scm.ts @@ -48,7 +48,18 @@ export class VirtualSCM implements Disposable { } private registerCommands() { - commands.registerCommand('githubBrowser.commit', (...args: any[]) => this.commitChanges(args[0])); + commands.registerCommand('githubBrowser.commit', (sourceControl: SourceControl | undefined) => { + // TODO@eamodio remove this hack once I figure out why the args are missing + if (sourceControl === undefined && this.providers.length === 1) { + sourceControl = this.providers[0].sourceControl; + } + + if (sourceControl === undefined) { + return; + } + + this.commitChanges(sourceControl); + }); commands.registerCommand('githubBrowser.discardChanges', (resourceState: SourceControlResourceState) => this.discardChanges(resourceState.resourceUri) From 156f541d4714e3d69e0993ef5c16ad217f1606fc Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Thu, 2 Jul 2020 12:02:53 -0700 Subject: [PATCH 85/93] Add telemetry for how often find widget is enabled in webviews We are trying to understand how many extensions use the find widget so that we can see the impact of switching to iframe based webviews --- .../webview/electron-browser/webviewElement.ts | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/vs/workbench/contrib/webview/electron-browser/webviewElement.ts b/src/vs/workbench/contrib/webview/electron-browser/webviewElement.ts index 84abb4f42e939..0ad394f8d3d42 100644 --- a/src/vs/workbench/contrib/webview/electron-browser/webviewElement.ts +++ b/src/vs/workbench/contrib/webview/electron-browser/webviewElement.ts @@ -127,6 +127,17 @@ export class ElectronWebviewBasedWebview extends BaseWebview impleme ) { super(id, options, contentOptions, extension, _webviewThemeDataProvider, _myLogService, telemetryService, environmentService, workbenchEnvironmentService); + /* __GDPR__ + "webview.createWebview" : { + "extension": { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, + "enableFindWidget": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true } + } + */ + telemetryService.publicLog('webview.createWebview', { + enableFindWidget: !!options.enableFindWidget, + extension: extension?.id.value, + }); + this._myLogService.debug(`Webview(${this.id}): init`); const webviewId = new Promise((resolve, reject) => { From b22fd30218adb5c7a65a854d0757e86303817cc3 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Thu, 2 Jul 2020 12:15:11 -0700 Subject: [PATCH 86/93] Make sure webview is focused before intercepting copy/paste Fixes #101599 --- .../contrib/webview/browser/webviewCommands.ts | 12 ++++++------ .../webview/electron-browser/webview.contribution.ts | 9 +++++++-- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/src/vs/workbench/contrib/webview/browser/webviewCommands.ts b/src/vs/workbench/contrib/webview/browser/webviewCommands.ts index 6d0ca158442ca..b3fb9164a2e51 100644 --- a/src/vs/workbench/contrib/webview/browser/webviewCommands.ts +++ b/src/vs/workbench/contrib/webview/browser/webviewCommands.ts @@ -32,7 +32,7 @@ export class ShowWebViewEditorFindWidgetAction extends Action2 { } public run(accessor: ServicesAccessor): void { - getFocusedWebviewEditor(accessor)?.showFind(); + getActiveWebview(accessor)?.showFind(); } } @@ -53,7 +53,7 @@ export class HideWebViewEditorFindCommand extends Action2 { } public run(accessor: ServicesAccessor): void { - getFocusedWebviewEditor(accessor)?.hideFind(); + getActiveWebview(accessor)?.hideFind(); } } @@ -74,7 +74,7 @@ export class WebViewEditorFindNextCommand extends Action2 { } public run(accessor: ServicesAccessor): void { - getFocusedWebviewEditor(accessor)?.runFindAction(false); + getActiveWebview(accessor)?.runFindAction(false); } } @@ -95,7 +95,7 @@ export class WebViewEditorFindPreviousCommand extends Action2 { } public run(accessor: ServicesAccessor): void { - getFocusedWebviewEditor(accessor)?.runFindAction(true); + getActiveWebview(accessor)?.runFindAction(true); } } @@ -117,7 +117,7 @@ export class SelectAllWebviewEditorCommand extends Action2 { } public run(accessor: ServicesAccessor): void { - getFocusedWebviewEditor(accessor)?.selectAll(); + getActiveWebview(accessor)?.selectAll(); } } @@ -142,7 +142,7 @@ export class ReloadWebviewAction extends Action { } } -export function getFocusedWebviewEditor(accessor: ServicesAccessor): Webview | undefined { +export function getActiveWebview(accessor: ServicesAccessor): Webview | undefined { const editorService = accessor.get(IEditorService); const activeEditor = editorService.activeEditor; return activeEditor instanceof WebviewInput ? activeEditor.webview : undefined; diff --git a/src/vs/workbench/contrib/webview/electron-browser/webview.contribution.ts b/src/vs/workbench/contrib/webview/electron-browser/webview.contribution.ts index 7c27fad181027..5344b204ab923 100644 --- a/src/vs/workbench/contrib/webview/electron-browser/webview.contribution.ts +++ b/src/vs/workbench/contrib/webview/electron-browser/webview.contribution.ts @@ -11,7 +11,7 @@ import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation import { Registry } from 'vs/platform/registry/common/platform'; import { Extensions as ActionExtensions, IWorkbenchActionRegistry } from 'vs/workbench/common/actions'; import { IWebviewService, webviewDeveloperCategory, WebviewOverlay } from 'vs/workbench/contrib/webview/browser/webview'; -import { getFocusedWebviewEditor } from 'vs/workbench/contrib/webview/browser/webviewCommands'; +import { getActiveWebview } from 'vs/workbench/contrib/webview/browser/webviewCommands'; import * as webviewCommands from 'vs/workbench/contrib/webview/electron-browser/webviewCommands'; import { ElectronWebviewBasedWebview } from 'vs/workbench/contrib/webview/electron-browser/webviewElement'; import { ElectronWebviewService } from 'vs/workbench/contrib/webview/electron-browser/webviewService'; @@ -26,11 +26,16 @@ actionRegistry.registerWorkbenchAction( webviewDeveloperCategory); function getActiveElectronBasedWebview(accessor: ServicesAccessor): ElectronWebviewBasedWebview | undefined { - const webview = getFocusedWebviewEditor(accessor); + const webview = getActiveWebview(accessor); if (!webview) { return undefined; } + // Make sure we are really focused on the webview + if (!['WEBVIEW', 'IFRAME'].includes(document.activeElement?.tagName ?? '')) { + return undefined; + } + if (webview instanceof ElectronWebviewBasedWebview) { return webview; } else if ('getInnerWebview' in (webview as WebviewOverlay)) { From 378ad1e184574551d7acb383e5448ff7e651818c Mon Sep 17 00:00:00 2001 From: Jackson Kearl Date: Thu, 2 Jul 2020 12:15:39 -0700 Subject: [PATCH 87/93] Dont overwrite context lines if defined in file --- .../workbench/contrib/searchEditor/browser/searchEditorInput.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/searchEditor/browser/searchEditorInput.ts b/src/vs/workbench/contrib/searchEditor/browser/searchEditorInput.ts index 36a7e3037d23b..cb5f5c99735b7 100644 --- a/src/vs/workbench/contrib/searchEditor/browser/searchEditorInput.ts +++ b/src/vs/workbench/contrib/searchEditor/browser/searchEditorInput.ts @@ -308,7 +308,7 @@ export const getOrMakeSearchEditorInput = ( let config = { ...defaultConfig, ...priorConfig, ...existingData.config }; if (defaultNumberOfContextLines !== null && defaultNumberOfContextLines !== undefined) { - config.contextLines = defaultNumberOfContextLines; + config.contextLines = existingData.config.contextLines ?? defaultNumberOfContextLines; } if (existingData.text) { From 2ddb2c5a720c89a70f4c81589ab362c1ef014bd4 Mon Sep 17 00:00:00 2001 From: Armando Aguirre Date: Thu, 2 Jul 2020 13:18:57 -0700 Subject: [PATCH 88/93] Added word boundary on tsserver regex (#101598) Adds a word boundary on the tsserver regex so that it doens't get confused by other file names. --- .../typescript-language-features/src/tsServer/serverError.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extensions/typescript-language-features/src/tsServer/serverError.ts b/extensions/typescript-language-features/src/tsServer/serverError.ts index ace77d8a90322..643998cd4ec3c 100644 --- a/extensions/typescript-language-features/src/tsServer/serverError.ts +++ b/extensions/typescript-language-features/src/tsServer/serverError.ts @@ -79,7 +79,7 @@ export class TypeScriptServerError extends Error { if (!message) { return ''; } - const regex = /(tsserver)?(\.(?:ts|tsx|js|jsx)(?::\d+(?::\d+)?)?)\)?$/igm; + const regex = /(\btsserver)?(\.(?:ts|tsx|js|jsx)(?::\d+(?::\d+)?)?)\)?$/igm; let serverStack = ''; while (true) { const match = regex.exec(message); From 1d8fdcab15cda8c46c640c037777b56b1d7c08f7 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Thu, 2 Jul 2020 22:50:44 +0200 Subject: [PATCH 89/93] Fixes #35711 * Take `window.zoomLevel` into account, as it impacts `window.devicePixelRatio` * Include linux in the check --- .../browser/ui/scrollbar/scrollableElement.ts | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/src/vs/base/browser/ui/scrollbar/scrollableElement.ts b/src/vs/base/browser/ui/scrollbar/scrollableElement.ts index f611236e379f9..00bb9830d54ff 100644 --- a/src/vs/base/browser/ui/scrollbar/scrollableElement.ts +++ b/src/vs/base/browser/ui/scrollbar/scrollableElement.ts @@ -17,6 +17,7 @@ import { Emitter, Event } from 'vs/base/common/event'; import { IDisposable, dispose } from 'vs/base/common/lifecycle'; import * as platform from 'vs/base/common/platform'; import { INewScrollDimensions, INewScrollPosition, IScrollDimensions, IScrollPosition, ScrollEvent, Scrollable, ScrollbarVisibility } from 'vs/base/common/scrollable'; +import { getZoomFactor } from 'vs/base/browser/browser'; const HIDE_TIMEOUT = 500; const SCROLL_WHEEL_SENSITIVITY = 50; @@ -130,13 +131,18 @@ export class MouseWheelClassifier { // } } - if (Math.abs(item.deltaX - Math.round(item.deltaX)) > 0 || Math.abs(item.deltaY - Math.round(item.deltaY)) > 0) { + if (!this._isAlmostInt(item.deltaX) || !this._isAlmostInt(item.deltaY)) { // non-integer deltas => indicator that this is not a physical mouse wheel score += 0.25; } return Math.min(Math.max(score, 0), 1); } + + private _isAlmostInt(value: number): boolean { + const delta = Math.abs(Math.round(value) - value); + return (delta < 0.01); + } } export abstract class AbstractScrollableElement extends Widget { @@ -343,10 +349,11 @@ export abstract class AbstractScrollableElement extends Widget { const classifier = MouseWheelClassifier.INSTANCE; if (SCROLL_WHEEL_SMOOTH_SCROLL_ENABLED) { - if (platform.isWindows) { - // On Windows, the incoming delta events are multiplied with the device pixel ratio, - // so to get a better classification, simply undo that. - classifier.accept(Date.now(), e.deltaX / window.devicePixelRatio, e.deltaY / window.devicePixelRatio); + const osZoomFactor = window.devicePixelRatio / getZoomFactor(); + if (platform.isWindows || platform.isLinux) { + // On Windows and Linux, the incoming delta events are multiplied with the OS zoom factor. + // The OS zoom factor can be reverse engineered by using the device pixel ratio and the configured zoom factor into account. + classifier.accept(Date.now(), e.deltaX / osZoomFactor, e.deltaY / osZoomFactor); } else { classifier.accept(Date.now(), e.deltaX, e.deltaY); } From 4019f351da8e1b8729fc02aabcd588f6514cd0a4 Mon Sep 17 00:00:00 2001 From: Miguel Solorio Date: Thu, 2 Jul 2020 13:57:48 -0700 Subject: [PATCH 90/93] =?UTF-8?q?=F0=9F=92=AA=20Trim=20more=20padding=20fr?= =?UTF-8?q?om=20notebook=20cells=20(refs=20#101600)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/vs/workbench/contrib/notebook/browser/constants.ts | 7 ++++--- .../workbench/contrib/notebook/browser/media/notebook.css | 3 +-- .../contrib/notebook/browser/notebookEditorWidget.ts | 6 +++--- .../notebook/browser/view/renderers/backLayerWebView.ts | 6 +++--- .../notebook/browser/viewModel/codeCellViewModel.ts | 2 +- 5 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/vs/workbench/contrib/notebook/browser/constants.ts b/src/vs/workbench/contrib/notebook/browser/constants.ts index e4b14689ee76d..cdc249042541d 100644 --- a/src/vs/workbench/contrib/notebook/browser/constants.ts +++ b/src/vs/workbench/contrib/notebook/browser/constants.ts @@ -8,9 +8,9 @@ export const SCROLLABLE_ELEMENT_PADDING_TOP = 20; // Cell sizing related -export const CELL_MARGIN = 16; +export const CELL_MARGIN = 8; export const CELL_RUN_GUTTER = 28; -export const CODE_CELL_LEFT_MARGIN = 44; +export const CODE_CELL_LEFT_MARGIN = 32; export const EDITOR_TOOLBAR_HEIGHT = 0; export const BOTTOM_CELL_TOOLBAR_HEIGHT = 28; @@ -22,5 +22,6 @@ export const CELL_BOTTOM_MARGIN = 6; // Top and bottom padding inside the monaco editor in a cell, which are included in `cell.editorHeight` export const EDITOR_TOP_PADDING = 12; -export const EDITOR_BOTTOM_PADDING = 12; +export const EDITOR_BOTTOM_PADDING = 4; +export const CELL_OUTPUT_PADDING = 14; diff --git a/src/vs/workbench/contrib/notebook/browser/media/notebook.css b/src/vs/workbench/contrib/notebook/browser/media/notebook.css index 793cd1294a897..70b8701a46c03 100644 --- a/src/vs/workbench/contrib/notebook/browser/media/notebook.css +++ b/src/vs/workbench/contrib/notebook/browser/media/notebook.css @@ -716,8 +716,7 @@ .monaco-workbench .notebookOverlay > .cell-list-container .notebook-folding-indicator .codicon { visibility: visible; - padding: 8px 4px 0; - width: calc(100% - 32px); + padding: 8px 0 0 10px; } /** Theming */ diff --git a/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts b/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts index 0ab698dd6f7dd..438996bd0abb0 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts @@ -1557,14 +1557,14 @@ registerThemingParticipant((theme, collector) => { } // Cell Margin - collector.addRule(`.notebookOverlay .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .monaco-list-row > div.cell { margin: 0px ${CELL_MARGIN}px 0px ${CELL_MARGIN}px; }`); + collector.addRule(`.notebookOverlay .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .monaco-list-row > div.cell { margin: 0px ${CELL_MARGIN * 2}px 0px ${CELL_MARGIN}px; }`); collector.addRule(`.notebookOverlay .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .monaco-list-row > div.cell.code { margin-left: ${CODE_CELL_LEFT_MARGIN}px; }`); collector.addRule(`.notebookOverlay .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .monaco-list-row { padding-top: ${EDITOR_TOP_MARGIN}px; }`); collector.addRule(`.notebookOverlay .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .markdown-cell-row { padding-bottom: ${CELL_BOTTOM_MARGIN}px; }`); collector.addRule(`.notebookOverlay .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .markdown-cell-row .cell-bottom-toolbar-container { margin-top: ${CELL_BOTTOM_MARGIN}px; }`); collector.addRule(`.notebookOverlay .output { margin: 0px ${CELL_MARGIN}px 0px ${CODE_CELL_LEFT_MARGIN + CELL_RUN_GUTTER}px; }`); collector.addRule(`.notebookOverlay .output { width: calc(100% - ${CODE_CELL_LEFT_MARGIN + CELL_RUN_GUTTER + CELL_MARGIN}px); }`); - collector.addRule(`.notebookOverlay .cell-bottom-toolbar-container { width: calc(100% - ${CELL_MARGIN * 2 + CELL_RUN_GUTTER}px); margin: 0px ${CELL_MARGIN}px 0px ${CELL_MARGIN + CELL_RUN_GUTTER}px; }`); + collector.addRule(`.notebookOverlay .cell-bottom-toolbar-container { width: calc(100% - ${CELL_MARGIN * 2 + CELL_RUN_GUTTER}px); margin: 0px ${CELL_MARGIN * 2}px 0px ${CELL_MARGIN + CELL_RUN_GUTTER}px; }`); collector.addRule(`.notebookOverlay .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .monaco-list-row > div.cell.markdown { padding-left: ${CELL_RUN_GUTTER}px; }`); collector.addRule(`.notebookOverlay .cell .run-button-container { width: ${CELL_RUN_GUTTER}px; }`); @@ -1572,7 +1572,7 @@ registerThemingParticipant((theme, collector) => { collector.addRule(`.notebookOverlay .monaco-list .monaco-list-row .cell-focus-indicator-top { height: ${EDITOR_TOP_MARGIN}px; }`); collector.addRule(`.notebookOverlay .monaco-list .monaco-list-row .cell-focus-indicator-side { bottom: ${BOTTOM_CELL_TOOLBAR_HEIGHT}px; }`); collector.addRule(`.notebookOverlay .monaco-list .monaco-list-row .cell-focus-indicator { width: ${CODE_CELL_LEFT_MARGIN + CELL_RUN_GUTTER}px; }`); - collector.addRule(`.notebookOverlay .monaco-list .monaco-list-row .cell-focus-indicator.cell-focus-indicator-right { width: ${CELL_MARGIN}px; }`); + collector.addRule(`.notebookOverlay .monaco-list .monaco-list-row .cell-focus-indicator.cell-focus-indicator-right { width: ${CELL_MARGIN * 2}px; }`); collector.addRule(`.notebookOverlay .monaco-list .monaco-list-row .cell-focus-indicator-bottom { height: ${CELL_BOTTOM_MARGIN}px; }`); collector.addRule(`.notebookOverlay .monaco-list .monaco-list-row .cell-shadow-container-bottom { top: ${CELL_BOTTOM_MARGIN}px; }`); }); diff --git a/src/vs/workbench/contrib/notebook/browser/view/renderers/backLayerWebView.ts b/src/vs/workbench/contrib/notebook/browser/view/renderers/backLayerWebView.ts index 387c4ce41ec47..7f28f9cec2370 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/renderers/backLayerWebView.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/renderers/backLayerWebView.ts @@ -13,7 +13,7 @@ import { URI } from 'vs/base/common/uri'; import * as UUID from 'vs/base/common/uuid'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; import { IOpenerService, matchesScheme } from 'vs/platform/opener/common/opener'; -import { CELL_MARGIN, CELL_RUN_GUTTER, CODE_CELL_LEFT_MARGIN } from 'vs/workbench/contrib/notebook/browser/constants'; +import { CELL_MARGIN, CELL_RUN_GUTTER, CODE_CELL_LEFT_MARGIN, CELL_OUTPUT_PADDING } from 'vs/workbench/contrib/notebook/browser/constants'; import { INotebookEditor } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; import { CodeCellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/codeCellViewModel'; import { CellOutputKind, IProcessedOutput } from 'vs/workbench/contrib/notebook/common/notebookCommon'; @@ -312,7 +312,7 @@ export class BackLayerWebView extends Disposable { if (!isWeb) { coreDependencies = ``; - const htmlContent = this.generateContent(8, coreDependencies, baseUrl.toString()); + const htmlContent = this.generateContent(CELL_OUTPUT_PADDING, coreDependencies, baseUrl.toString()); this.initialize(htmlContent); resolveFunc!(); } else { @@ -329,7 +329,7 @@ ${loaderJs} `; - const htmlContent = this.generateContent(8, coreDependencies, baseUrl.toString()); + const htmlContent = this.generateContent(CELL_OUTPUT_PADDING, coreDependencies, baseUrl.toString()); this.initialize(htmlContent); resolveFunc!(); }); diff --git a/src/vs/workbench/contrib/notebook/browser/viewModel/codeCellViewModel.ts b/src/vs/workbench/contrib/notebook/browser/viewModel/codeCellViewModel.ts index 728c79882d2e5..144c3ad17ca7f 100644 --- a/src/vs/workbench/contrib/notebook/browser/viewModel/codeCellViewModel.ts +++ b/src/vs/workbench/contrib/notebook/browser/viewModel/codeCellViewModel.ts @@ -92,7 +92,7 @@ export class CodeCellViewModel extends BaseCellViewModel implements ICellViewMod } private computeEditorWidth(outerWidth: number): number { - return outerWidth - (CODE_CELL_LEFT_MARGIN + CELL_MARGIN + CELL_RUN_GUTTER); + return outerWidth - (CODE_CELL_LEFT_MARGIN + (CELL_MARGIN * 2) + CELL_RUN_GUTTER); } layoutChange(state: CodeCellLayoutChangeEvent) { From f3280356e4f779fda38d87f6eaaf71c73fdf655c Mon Sep 17 00:00:00 2001 From: Miguel Solorio Date: Thu, 2 Jul 2020 14:32:30 -0700 Subject: [PATCH 91/93] Remove empty line --- .vscode/notebooks/my-work.github-issues | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.vscode/notebooks/my-work.github-issues b/.vscode/notebooks/my-work.github-issues index c6d2309b392fe..dc6d33365d797 100644 --- a/.vscode/notebooks/my-work.github-issues +++ b/.vscode/notebooks/my-work.github-issues @@ -20,7 +20,7 @@ { "kind": 2, "language": "github-issues", - "value": "$repos $milestone assignee:@me is:open\n", + "value": "$repos $milestone assignee:@me is:open", "editable": false }, { From 2ce03eed5a61e9a7cb7837861d80b62a83cf6841 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Thu, 2 Jul 2020 16:41:23 -0700 Subject: [PATCH 92/93] Update VS Code refactoring support for new TS 4.0 api Adopts changes from https://github.com/microsoft/TypeScript/pull/37871/ --- .../src/features/fileConfigurationManager.ts | 10 +++++++++- .../src/features/refactor.ts | 18 +++++++++--------- 2 files changed, 18 insertions(+), 10 deletions(-) diff --git a/extensions/typescript-language-features/src/features/fileConfigurationManager.ts b/extensions/typescript-language-features/src/features/fileConfigurationManager.ts index 0d54ccea22a8e..55d5324469bfc 100644 --- a/extensions/typescript-language-features/src/features/fileConfigurationManager.ts +++ b/extensions/typescript-language-features/src/features/fileConfigurationManager.ts @@ -13,6 +13,13 @@ import { isTypeScriptDocument } from '../utils/languageModeIds'; import { equals } from '../utils/objects'; import { ResourceMap } from '../utils/resourceMap'; +namespace Experimental { + // https://github.com/microsoft/TypeScript/pull/37871/ + export interface UserPreferences extends Proto.UserPreferences { + readonly provideRefactorNotApplicableReason?: boolean; + } +} + interface FileConfiguration { readonly formatOptions: Proto.FormatCodeSettings; readonly preferences: Proto.UserPreferences; @@ -170,7 +177,7 @@ export default class FileConfigurationManager extends Disposable { isTypeScriptDocument(document) ? 'typescript.preferences' : 'javascript.preferences', document.uri); - const preferences: Proto.UserPreferences = { + const preferences: Experimental.UserPreferences = { quotePreference: this.getQuoteStylePreference(preferencesConfig), importModuleSpecifierPreference: getImportModuleSpecifierPreference(preferencesConfig), importModuleSpecifierEnding: getImportModuleSpecifierEndingPreference(preferencesConfig), @@ -178,6 +185,7 @@ export default class FileConfigurationManager extends Disposable { providePrefixAndSuffixTextForRename: preferencesConfig.get('renameShorthandProperties', true) === false ? false : preferencesConfig.get('useAliasesForRenames', true), allowRenameOfImportPath: true, includeAutomaticOptionalChainCompletions: config.get('suggest.includeAutomaticOptionalChainCompletions', true), + provideRefactorNotApplicableReason: true, }; return preferences; diff --git a/extensions/typescript-language-features/src/features/refactor.ts b/extensions/typescript-language-features/src/features/refactor.ts index b3b9376af2040..ca56c6d690209 100644 --- a/extensions/typescript-language-features/src/features/refactor.ts +++ b/extensions/typescript-language-features/src/features/refactor.ts @@ -22,7 +22,7 @@ const localize = nls.loadMessageBundle(); namespace Experimental { export interface RefactorActionInfo extends Proto.RefactorActionInfo { - readonly error?: string + readonly notApplicableReason?: string; } export type RefactorTriggerReason = 'implicit' | 'invoked'; @@ -312,16 +312,16 @@ class TypeScriptRefactorProvider implements vscode.CodeActionProvider { const codeAction = new vscode.CodeAction(action.description, TypeScriptRefactorProvider.getKind(action)); // https://github.com/microsoft/TypeScript/pull/37871 - if (action.error) { - codeAction.disabled = { reason: action.error }; - return codeAction; + if (action.notApplicableReason) { + codeAction.disabled = { reason: action.notApplicableReason }; + } else { + codeAction.command = { + title: action.description, + command: ApplyRefactoringCommand.ID, + arguments: [document, info.name, action.name, rangeOrSelection], + }; } - codeAction.command = { - title: action.description, - command: ApplyRefactoringCommand.ID, - arguments: [document, info.name, action.name, rangeOrSelection], - }; codeAction.isPreferred = TypeScriptRefactorProvider.isPreferred(action, allActions); return codeAction; } From e38c2d293da8f435d408afaf7f35a20cf3a10d30 Mon Sep 17 00:00:00 2001 From: Connor Peet Date: Thu, 2 Jul 2020 16:34:33 -0700 Subject: [PATCH 93/93] debug: final js-debug update for 1.47 --- product.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/product.json b/product.json index 3986c1e913007..79affc5128635 100644 --- a/product.json +++ b/product.json @@ -90,7 +90,7 @@ }, { "name": "ms-vscode.js-debug", - "version": "1.47.1", + "version": "1.47.2", "repo": "https://github.com/Microsoft/vscode-js-debug", "metadata": { "id": "25629058-ddac-4e17-abba-74678e126c5d",