From a10080241273194235d20efbcebc14a56143a560 Mon Sep 17 00:00:00 2001 From: Sergio Schvezov Date: Fri, 21 Feb 2020 15:57:30 -0300 Subject: [PATCH 01/74] snap launcher: fix quoting in script Avoid any potential issue with globbing or word splitting. Signed-off-by: Sergio Schvezov --- resources/linux/snap/electron-launch | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/resources/linux/snap/electron-launch b/resources/linux/snap/electron-launch index 2a1c4395187..8a294975147 100755 --- a/resources/linux/snap/electron-launch +++ b/resources/linux/snap/electron-launch @@ -2,7 +2,7 @@ # On Fedora $SNAP is under /var and there is some magic to map it to /snap. # We need to handle that case and reset $SNAP -SNAP=$(echo $SNAP | sed -e "s|/var/lib/snapd||g") +SNAP=$(echo "$SNAP" | sed -e "s|/var/lib/snapd||g") if [ "$SNAP_ARCH" == "amd64" ]; then ARCH="x86_64-linux-gnu" @@ -14,21 +14,21 @@ else ARCH="$SNAP_ARCH-linux-gnu" fi -export XDG_CACHE_HOME=$SNAP_USER_COMMON/.cache -if [[ -d $SNAP_USER_DATA/.cache && ! -e $XDG_CACHE_HOME ]]; then +export XDG_CACHE_HOME="$SNAP_USER_COMMON/.cache" +if [[ -d "$SNAP_USER_DATA/.cache" && ! -e "$XDG_CACHE_HOME" ]]; then # the .cache directory used to be stored under $SNAP_USER_DATA, migrate it - mv $SNAP_USER_DATA/.cache $SNAP_USER_COMMON/ + mv "$SNAP_USER_DATA/.cache" "$SNAP_USER_COMMON/" fi -mkdir -p $XDG_CACHE_HOME +mkdir -p "$XDG_CACHE_HOME" # Gdk-pixbuf loaders -export GDK_PIXBUF_MODULE_FILE=$XDG_CACHE_HOME/gdk-pixbuf-loaders.cache -export GDK_PIXBUF_MODULEDIR=$SNAP/usr/lib/$ARCH/gdk-pixbuf-2.0/2.10.0/loaders -if [ -f $SNAP/usr/lib/$ARCH/gdk-pixbuf-2.0/gdk-pixbuf-query-loaders ]; then - $SNAP/usr/lib/$ARCH/gdk-pixbuf-2.0/gdk-pixbuf-query-loaders > $GDK_PIXBUF_MODULE_FILE +export GDK_PIXBUF_MODULE_FILE="$XDG_CACHE_HOME/gdk-pixbuf-loaders.cache" +export GDK_PIXBUF_MODULEDIR="$SNAP/usr/lib/$ARCH/gdk-pixbuf-2.0/2.10.0/loaders" +if [ -f "$SNAP/usr/lib/$ARCH/gdk-pixbuf-2.0/gdk-pixbuf-query-loaders" ]; then + "$SNAP/usr/lib/$ARCH/gdk-pixbuf-2.0/gdk-pixbuf-query-loaders" > "$GDK_PIXBUF_MODULE_FILE" fi # Create $XDG_RUNTIME_DIR if not exists (to be removed when https://pad.lv/1656340 is fixed) -[ -n "$XDG_RUNTIME_DIR" ] && mkdir -p $XDG_RUNTIME_DIR -m 700 +[ -n "$XDG_RUNTIME_DIR" ] && mkdir -p "$XDG_RUNTIME_DIR" -m 700 exec "$@" From d4da28357f193bd2d44eb5bd50ff877b8742b22c Mon Sep 17 00:00:00 2001 From: Sergio Schvezov Date: Fri, 21 Feb 2020 17:26:57 -0300 Subject: [PATCH 02/74] snap launcher: avoid exporting XDG_CACHE_HOME Exporting XDG_CACHE_HOME affects applications launched from within the context of code. Rename it to GDK_CACHE_DIR and do not export it. Also test for existence before creating to avoid shelling out to mkdir if not needed. Signed-off-by: Sergio Schvezov --- resources/linux/snap/electron-launch | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/resources/linux/snap/electron-launch b/resources/linux/snap/electron-launch index 8a294975147..9f4eb6a23b8 100755 --- a/resources/linux/snap/electron-launch +++ b/resources/linux/snap/electron-launch @@ -14,15 +14,15 @@ else ARCH="$SNAP_ARCH-linux-gnu" fi -export XDG_CACHE_HOME="$SNAP_USER_COMMON/.cache" -if [[ -d "$SNAP_USER_DATA/.cache" && ! -e "$XDG_CACHE_HOME" ]]; then +GDK_CACHE_DIR="$SNAP_USER_COMMON/.cache" +if [[ -d "$SNAP_USER_DATA/.cache" && ! -e "$GDK_CACHE_DIR" ]]; then # the .cache directory used to be stored under $SNAP_USER_DATA, migrate it mv "$SNAP_USER_DATA/.cache" "$SNAP_USER_COMMON/" fi -mkdir -p "$XDG_CACHE_HOME" +[ ! -d "$GDK_CACHE_DIR" ] && mkdir -p "$GDK_CACHE_DIR" # Gdk-pixbuf loaders -export GDK_PIXBUF_MODULE_FILE="$XDG_CACHE_HOME/gdk-pixbuf-loaders.cache" +export GDK_PIXBUF_MODULE_FILE="$GDK_CACHE_DIR/gdk-pixbuf-loaders.cache" export GDK_PIXBUF_MODULEDIR="$SNAP/usr/lib/$ARCH/gdk-pixbuf-2.0/2.10.0/loaders" if [ -f "$SNAP/usr/lib/$ARCH/gdk-pixbuf-2.0/gdk-pixbuf-query-loaders" ]; then "$SNAP/usr/lib/$ARCH/gdk-pixbuf-2.0/gdk-pixbuf-query-loaders" > "$GDK_PIXBUF_MODULE_FILE" From d9507c90f6c60ed351eb8ab4c12530a563d18949 Mon Sep 17 00:00:00 2001 From: Gordey Levchenko Date: Wed, 26 Feb 2020 01:46:51 +0600 Subject: [PATCH 03/74] Add separator for sync setting --- src/vs/workbench/contrib/preferences/browser/settingsTree.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/vs/workbench/contrib/preferences/browser/settingsTree.ts b/src/vs/workbench/contrib/preferences/browser/settingsTree.ts index c1a674828f9..dedf95bbe56 100644 --- a/src/vs/workbench/contrib/preferences/browser/settingsTree.ts +++ b/src/vs/workbench/contrib/preferences/browser/settingsTree.ts @@ -1205,6 +1205,7 @@ export class SettingTreeRenderers { new Separator(), this._instantiationService.createInstance(CopySettingIdAction), this._instantiationService.createInstance(CopySettingAsJSONAction), + new Separator(), ]; const actionFactory = (setting: ISetting) => this.getActionsForSetting(setting); From 7a13028b705142564dc582eafaf5b3e0e5dfddf7 Mon Sep 17 00:00:00 2001 From: Rachel Macfarlane Date: Wed, 26 Feb 2020 15:06:53 -0800 Subject: [PATCH 04/74] Lowercase auth provider ids, fixes #91538 --- extensions/github-authentication/src/extension.ts | 2 +- extensions/vscode-account/src/extension.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/extensions/github-authentication/src/extension.ts b/extensions/github-authentication/src/extension.ts index 943db6f20b5..c377e020939 100644 --- a/extensions/github-authentication/src/extension.ts +++ b/extensions/github-authentication/src/extension.ts @@ -16,7 +16,7 @@ export async function activate(context: vscode.ExtensionContext) { await loginService.initialize(); vscode.authentication.registerAuthenticationProvider({ - id: 'GitHub', + id: 'github', displayName: 'GitHub', onDidChangeSessions: onDidChangeSessions.event, getSessions: () => Promise.resolve(loginService.sessions), diff --git a/extensions/vscode-account/src/extension.ts b/extensions/vscode-account/src/extension.ts index fa94280fe3d..e70fbe59cb0 100644 --- a/extensions/vscode-account/src/extension.ts +++ b/extensions/vscode-account/src/extension.ts @@ -18,7 +18,7 @@ export async function activate(context: vscode.ExtensionContext) { await loginService.initialize(); context.subscriptions.push(vscode.authentication.registerAuthenticationProvider({ - id: 'MSA', + id: 'microsoft', displayName: 'Microsoft', onDidChangeSessions: onDidChangeSessions.event, getSessions: () => Promise.resolve(loginService.sessions), From 438b39e016a6852f9ebb224b98fbf81ac8033aac Mon Sep 17 00:00:00 2001 From: SteVen Batten Date: Wed, 26 Feb 2020 15:13:21 -0800 Subject: [PATCH 05/74] fixes #91622 --- src/vs/workbench/browser/actions/layoutActions.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/browser/actions/layoutActions.ts b/src/vs/workbench/browser/actions/layoutActions.ts index f03e93dd95f..0ece351afc3 100644 --- a/src/vs/workbench/browser/actions/layoutActions.ts +++ b/src/vs/workbench/browser/actions/layoutActions.ts @@ -553,7 +553,7 @@ export class MoveFocusedViewAction extends Action { const viewDescriptor = this.viewDescriptorService.getViewDescriptor(focusedViewId); if (!viewDescriptor || !viewDescriptor.canMoveView) { - this.notificationService.error(nls.localize('moveFocusedView.error.nonMovableView', "The currently focused view is not movable {0}.", focusedViewId)); + this.notificationService.error(nls.localize('moveFocusedView.error.nonMovableView', "The currently focused view is not movable.")); return Promise.resolve(); } From 8d19b6982eefc742dd9e4102f29157735b9fbdd8 Mon Sep 17 00:00:00 2001 From: Jackson Kearl Date: Wed, 26 Feb 2020 15:19:39 -0800 Subject: [PATCH 06/74] Fix #91559 --- src/vs/workbench/contrib/searchEditor/browser/searchEditor.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/vs/workbench/contrib/searchEditor/browser/searchEditor.ts b/src/vs/workbench/contrib/searchEditor/browser/searchEditor.ts index 8f26a359018..a32b0f8fc23 100644 --- a/src/vs/workbench/contrib/searchEditor/browser/searchEditor.ts +++ b/src/vs/workbench/contrib/searchEditor/browser/searchEditor.ts @@ -194,6 +194,7 @@ export class SearchEditor extends BaseTextEditor { const runAgainLink = DOM.append(this.messageBox, DOM.$('a.pointer.prominent.message', {}, localize('runSearch', "Run Search"))); this.messageDisposables.push(DOM.addDisposableListener(runAgainLink, DOM.EventType.CLICK, async () => { await this.triggerSearch(); + this.searchResultEditor.focus(); this.toggleRunAgainMessage(false); })); } From eee9122c870f32eccac1084d5dd10a2d7b153de5 Mon Sep 17 00:00:00 2001 From: Rachel Macfarlane Date: Wed, 26 Feb 2020 15:24:47 -0800 Subject: [PATCH 07/74] accessToken -> getAccessToken, fixes #91570 --- extensions/github-authentication/src/github.ts | 6 +++--- extensions/vscode-account/src/AADHelper.ts | 2 +- src/vs/editor/common/modes.ts | 2 +- src/vs/vscode.proposed.d.ts | 2 +- src/vs/workbench/api/browser/mainThreadAuthentication.ts | 4 ++-- src/vs/workbench/api/common/extHostAuthentication.ts | 6 +++--- .../workbench/contrib/userDataSync/browser/userDataSync.ts | 2 +- 7 files changed, 12 insertions(+), 12 deletions(-) diff --git a/extensions/github-authentication/src/github.ts b/extensions/github-authentication/src/github.ts index 0f46d20d81b..52c7c4e333a 100644 --- a/extensions/github-authentication/src/github.ts +++ b/extensions/github-authentication/src/github.ts @@ -71,7 +71,7 @@ export class GitHubAuthenticationProvider { id: session.id, accountName: session.accountName, scopes: session.scopes, - accessToken: () => Promise.resolve(session.accessToken) + getAccessToken: () => Promise.resolve(session.accessToken) }; }); } catch (e) { @@ -84,7 +84,7 @@ export class GitHubAuthenticationProvider { private async storeSessions(): Promise { const sessionData: SessionData[] = await Promise.all(this._sessions.map(async session => { - const resolvedAccessToken = await session.accessToken(); + const resolvedAccessToken = await session.getAccessToken(); return { id: session.id, accountName: session.accountName, @@ -111,7 +111,7 @@ export class GitHubAuthenticationProvider { const userInfo = await this._githubServer.getUserInfo(token); return { id: userInfo.id, - accessToken: () => Promise.resolve(token), + getAccessToken: () => Promise.resolve(token), accountName: userInfo.accountName, scopes: scopes }; diff --git a/extensions/vscode-account/src/AADHelper.ts b/extensions/vscode-account/src/AADHelper.ts index 5f193828141..b1aee3e6bdf 100644 --- a/extensions/vscode-account/src/AADHelper.ts +++ b/extensions/vscode-account/src/AADHelper.ts @@ -184,7 +184,7 @@ export class AzureActiveDirectoryService { private convertToSession(token: IToken): vscode.AuthenticationSession { return { id: token.sessionId, - accessToken: () => this.resolveAccessToken(token), + getAccessToken: () => this.resolveAccessToken(token), accountName: token.accountName, scopes: token.scope.split(' ') }; diff --git a/src/vs/editor/common/modes.ts b/src/vs/editor/common/modes.ts index 98af16d123d..b93301c609d 100644 --- a/src/vs/editor/common/modes.ts +++ b/src/vs/editor/common/modes.ts @@ -1373,7 +1373,7 @@ export interface RenameProvider { */ export interface AuthenticationSession { id: string; - accessToken(): Thenable; + getAccessToken(): Thenable; accountName: string; } diff --git a/src/vs/vscode.proposed.d.ts b/src/vs/vscode.proposed.d.ts index 89e14e3ddc9..86cb76837b3 100644 --- a/src/vs/vscode.proposed.d.ts +++ b/src/vs/vscode.proposed.d.ts @@ -20,7 +20,7 @@ declare module 'vscode' { export interface AuthenticationSession { id: string; - accessToken(): Thenable; + getAccessToken(): Thenable; accountName: string; scopes: string[] } diff --git a/src/vs/workbench/api/browser/mainThreadAuthentication.ts b/src/vs/workbench/api/browser/mainThreadAuthentication.ts index 22f91f6d2cc..15af9ba8bc6 100644 --- a/src/vs/workbench/api/browser/mainThreadAuthentication.ts +++ b/src/vs/workbench/api/browser/mainThreadAuthentication.ts @@ -25,7 +25,7 @@ export class MainThreadAuthenticationProvider { return { id: session.id, accountName: session.accountName, - accessToken: () => this._proxy.$getSessionAccessToken(this.id, session.id) + getAccessToken: () => this._proxy.$getSessionAccessToken(this.id, session.id) }; }); } @@ -35,7 +35,7 @@ export class MainThreadAuthenticationProvider { return { id: session.id, accountName: session.accountName, - accessToken: () => this._proxy.$getSessionAccessToken(this.id, session.id) + getAccessToken: () => this._proxy.$getSessionAccessToken(this.id, session.id) }; }); } diff --git a/src/vs/workbench/api/common/extHostAuthentication.ts b/src/vs/workbench/api/common/extHostAuthentication.ts index 234de7348f3..b3b2d4d0f4a 100644 --- a/src/vs/workbench/api/common/extHostAuthentication.ts +++ b/src/vs/workbench/api/common/extHostAuthentication.ts @@ -34,7 +34,7 @@ export class AuthenticationProviderWrapper implements vscode.AuthenticationProvi id: session.id, accountName: session.accountName, scopes: session.scopes, - accessToken: async () => { + getAccessToken: async () => { const isAllowed = await this._proxy.$getSessionsPrompt( this._provider.id, this.displayName, @@ -45,7 +45,7 @@ export class AuthenticationProviderWrapper implements vscode.AuthenticationProvi throw new Error('User did not consent to token access.'); } - return session.accessToken(); + return session.getAccessToken(); } }; }); @@ -137,7 +137,7 @@ export class ExtHostAuthentication implements ExtHostAuthenticationShape { const sessions = await authProvider.getSessions(); const session = sessions.find(session => session.id === sessionId); if (session) { - return session.accessToken(); + return session.getAccessToken(); } throw new Error(`Unable to find session with id: ${sessionId}`); diff --git a/src/vs/workbench/contrib/userDataSync/browser/userDataSync.ts b/src/vs/workbench/contrib/userDataSync/browser/userDataSync.ts index 8bf9147ddcb..3399c0adb64 100644 --- a/src/vs/workbench/contrib/userDataSync/browser/userDataSync.ts +++ b/src/vs/workbench/contrib/userDataSync/browser/userDataSync.ts @@ -226,7 +226,7 @@ export class UserDataSyncWorkbenchContribution extends Disposable implements IWo if (account) { try { - const token = await account.accessToken(); + const token = await account.getAccessToken(); this.authTokenService.setToken(token); this.authenticationState.set(AuthStatus.SignedIn); } catch (e) { From 75d8eee5648abe963b451e5452fc4a521f16cce1 Mon Sep 17 00:00:00 2001 From: SteVen Batten Date: Wed, 26 Feb 2020 15:28:40 -0800 Subject: [PATCH 08/74] fixes #91620 --- .../workbench/contrib/files/browser/media/explorerviewlet.css | 4 ++-- .../workbench/contrib/files/browser/views/openEditorsView.ts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/vs/workbench/contrib/files/browser/media/explorerviewlet.css b/src/vs/workbench/contrib/files/browser/media/explorerviewlet.css index e7e32d6ff20..04e0bf24825 100644 --- a/src/vs/workbench/contrib/files/browser/media/explorerviewlet.css +++ b/src/vs/workbench/contrib/files/browser/media/explorerviewlet.css @@ -55,11 +55,11 @@ align-items: center; } -.explorer-viewlet .pane-header .monaco-count-badge.hidden { +.pane-header .dirty-count.monaco-count-badge.hidden { display: none; } -.explorer-viewlet .monaco-count-badge { +.dirty-count.monaco-count-badge { padding: 1px 6px 2px; margin-left: 6px; min-height: auto; diff --git a/src/vs/workbench/contrib/files/browser/views/openEditorsView.ts b/src/vs/workbench/contrib/files/browser/views/openEditorsView.ts index c388727aba4..9c5162d1999 100644 --- a/src/vs/workbench/contrib/files/browser/views/openEditorsView.ts +++ b/src/vs/workbench/contrib/files/browser/views/openEditorsView.ts @@ -185,7 +185,7 @@ export class OpenEditorsView extends ViewPane { super.renderHeaderTitle(container, this.title); const count = dom.append(container, $('.count')); - this.dirtyCountElement = dom.append(count, $('.monaco-count-badge')); + this.dirtyCountElement = dom.append(count, $('.dirty-count.monaco-count-badge')); this._register((attachStylerCallback(this.themeService, { badgeBackground, badgeForeground, contrastBorder }, colors => { const background = colors.badgeBackground ? colors.badgeBackground.toString() : ''; From c5944491c0a4d2ac3b2a21d10201512587976438 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Wed, 26 Feb 2020 15:52:03 -0800 Subject: [PATCH 09/74] Improving documentation for custom editors --- src/vs/vscode.proposed.d.ts | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/src/vs/vscode.proposed.d.ts b/src/vs/vscode.proposed.d.ts index 86cb76837b3..b3bea7c0a5a 100644 --- a/src/vs/vscode.proposed.d.ts +++ b/src/vs/vscode.proposed.d.ts @@ -1279,8 +1279,8 @@ declare module 'vscode' { /** * Represents a custom document for a custom webview editor. * - * Custom documents are only used within a given `WebviewCustomEditorProvider`. The lifecycle of a - * `WebviewEditorCustomDocument` is managed by VS Code. When more more references remain to a given `WebviewEditorCustomDocument` + * Custom documents are only used within a given `CustomEditorProvider`. The lifecycle of a + * `CustomDocument` is managed by VS Code. When more more references remain to a given `CustomDocument` * then it is disposed of. * * @param UserDataType Type of custom object that extensions can store on the document. @@ -1297,7 +1297,7 @@ declare module 'vscode' { readonly uri: Uri; /** - * Event fired when there are no more references to the `WebviewEditorCustomDocument`. + * Event fired when there are no more references to the `CustomDocument`. */ readonly onDidDispose: Event; @@ -1313,7 +1313,7 @@ declare module 'vscode' { /** * Provider for webview editors that use a custom data model. * - * Custom webview editors use [`WebviewEditorCustomDocument`](#WebviewEditorCustomDocument) as their data model. + * Custom webview editors use [`CustomDocument`](#CustomDocument) as their data model. * This gives extensions full control over actions such as edit, save, and backup. * * You should use custom text based editors when dealing with binary files or more complex scenarios. For simple text @@ -1321,20 +1321,22 @@ declare module 'vscode' { */ export interface CustomEditorProvider { /** - * Create the model for a given + * Resolve the model for a given resource. * - * @param document Resource being resolved. + * @param document Document to resolve. + * + * @return The capabilities of the resolved document. */ resolveCustomDocument(document: CustomDocument): Thenable; /** * Resolve a webview editor for a given resource. * - * To resolve a webview editor, a provider must fill in its initial html content and hook up all + * To resolve a webview editor, the provider must fill in its initial html content and hook up all * the event listeners it is interested it. The provider should also take ownership of the passed in `WebviewPanel`. * - * @param document Document for resource being resolved. - * @param webviewPanel Webview being resolved. The provider should take ownership of this webview. + * @param document Document for the resource being resolved. + * @param webviewPanel Webview to resolve. The provider should take ownership of this webview. * * @return Thenable indicating that the webview editor has been resolved. */ @@ -1349,7 +1351,7 @@ declare module 'vscode' { * undo and backup. The provider is responsible for synchronizing text changes between the webview and the `TextDocument`. * * You should use text based webview editors when dealing with text based file formats, such as `xml` or `json`. - * For binary files or more specialized use cases, see [WebviewCustomEditorProvider](#WebviewCustomEditorProvider). + * For binary files or more specialized use cases, see [CustomEditorProvider](#CustomEditorProvider). */ export interface CustomTextEditorProvider { /** @@ -1359,7 +1361,7 @@ declare module 'vscode' { * the event listeners it is interested it. The provider should also take ownership of the passed in `WebviewPanel`. * * @param document Resource being resolved. - * @param webviewPanel Webview being resolved. The provider should take ownership of this webview. + * @param webviewPanel Webview to resolve. The provider should take ownership of this webview. * * @return Thenable indicating that the webview editor has been resolved. */ From 027da88563a9551046782b599a7b67788b3d43d9 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Wed, 26 Feb 2020 16:03:10 -0800 Subject: [PATCH 10/74] Use constant --- .../src/features/fileConfigurationManager.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/extensions/typescript-language-features/src/features/fileConfigurationManager.ts b/extensions/typescript-language-features/src/features/fileConfigurationManager.ts index cad4e5196b9..825a3049cba 100644 --- a/extensions/typescript-language-features/src/features/fileConfigurationManager.ts +++ b/extensions/typescript-language-features/src/features/fileConfigurationManager.ts @@ -7,9 +7,10 @@ import * as vscode from 'vscode'; import type * as Proto from '../protocol'; import { ITypeScriptServiceClient } from '../typescriptService'; import API from '../utils/api'; +import { Disposable } from '../utils/dispose'; +import * as fileSchemes from '../utils/fileSchemes'; import { isTypeScriptDocument } from '../utils/languageModeIds'; import { ResourceMap } from '../utils/resourceMap'; -import { Disposable } from '../utils/dispose'; function objsAreEqual(a: T, b: T): boolean { @@ -185,7 +186,7 @@ export default class FileConfigurationManager extends Disposable { return { quotePreference: this.getQuoteStylePreference(config), importModuleSpecifierPreference: getImportModuleSpecifierPreference(config), - allowTextChangesInNewFiles: document.uri.scheme === 'file', + allowTextChangesInNewFiles: document.uri.scheme === fileSchemes.file, providePrefixAndSuffixTextForRename: config.get('renameShorthandProperties', true), allowRenameOfImportPath: true, }; From e4beca6b31a6d991322069896294d448637b57bb Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Wed, 26 Feb 2020 16:03:40 -0800 Subject: [PATCH 11/74] Remove TS 3.7 protocol workaround --- .../src/features/fileConfigurationManager.ts | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/extensions/typescript-language-features/src/features/fileConfigurationManager.ts b/extensions/typescript-language-features/src/features/fileConfigurationManager.ts index 825a3049cba..4a625231458 100644 --- a/extensions/typescript-language-features/src/features/fileConfigurationManager.ts +++ b/extensions/typescript-language-features/src/features/fileConfigurationManager.ts @@ -145,9 +145,7 @@ export default class FileConfigurationManager extends Disposable { isTypeScriptDocument(document) ? 'typescript.format' : 'javascript.format', document.uri); - // `semicolons` added to `Proto.FormatCodeSettings` in TypeScript 3.7: - // remove intersection type after upgrading TypeScript. - const settings: Proto.FormatCodeSettings & { semicolons?: string } = { + return { tabSize: options.tabSize, indentSize: options.tabSize, convertTabsToSpaces: options.insertSpaces, @@ -170,8 +168,6 @@ export default class FileConfigurationManager extends Disposable { placeOpenBraceOnNewLineForControlBlocks: config.get('placeOpenBraceOnNewLineForControlBlocks'), semicolons: config.get('semicolons'), }; - - return settings; } private getPreferences(document: vscode.TextDocument): Proto.UserPreferences { From 24aeb687f73773be5c539e93f2e21d0f56d00edb Mon Sep 17 00:00:00 2001 From: Jackson Kearl Date: Wed, 26 Feb 2020 16:10:13 -0800 Subject: [PATCH 12/74] Add rerun action and icon. Close #91508. --- .../contrib/searchEditor/browser/constants.ts | 2 ++ .../browser/searchEditor.contribution.ts | 30 +++++++++++-------- .../searchEditor/browser/searchEditor.ts | 4 +-- .../browser/searchEditorActions.ts | 18 +++++++++++ 4 files changed, 40 insertions(+), 14 deletions(-) diff --git a/src/vs/workbench/contrib/searchEditor/browser/constants.ts b/src/vs/workbench/contrib/searchEditor/browser/constants.ts index 3de68eda5a0..7de8978e745 100644 --- a/src/vs/workbench/contrib/searchEditor/browser/constants.ts +++ b/src/vs/workbench/contrib/searchEditor/browser/constants.ts @@ -22,3 +22,5 @@ export const SearchEditorScheme = 'search-editor'; export const SearchEditorBodyScheme = 'search-editor-body'; export const SearchEditorFindMatchClass = 'seaarchEditorFindMatch'; + +export const SearchEditorID = 'workbench.editor.searchEditor'; diff --git a/src/vs/workbench/contrib/searchEditor/browser/searchEditor.contribution.ts b/src/vs/workbench/contrib/searchEditor/browser/searchEditor.contribution.ts index 57b857a860d..eb2646630b4 100644 --- a/src/vs/workbench/contrib/searchEditor/browser/searchEditor.contribution.ts +++ b/src/vs/workbench/contrib/searchEditor/browser/searchEditor.contribution.ts @@ -9,7 +9,7 @@ import { endsWith } from 'vs/base/common/strings'; import { URI } from 'vs/base/common/uri'; import { ToggleCaseSensitiveKeybinding, ToggleRegexKeybinding, ToggleWholeWordKeybinding } from 'vs/editor/contrib/find/findModel'; import { localize } from 'vs/nls'; -import { SyncActionDescriptor } from 'vs/platform/actions/common/actions'; +import { SyncActionDescriptor, MenuRegistry, MenuId } from 'vs/platform/actions/common/actions'; import { ContextKeyExpr, IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; @@ -20,11 +20,11 @@ import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { EditorDescriptor, Extensions as EditorExtensions, IEditorRegistry } from 'vs/workbench/browser/editor'; import { Extensions as ActionExtensions, IWorkbenchActionRegistry } from 'vs/workbench/common/actions'; import { Extensions as WorkbenchExtensions, IWorkbenchContribution, IWorkbenchContributionsRegistry } from 'vs/workbench/common/contributions'; -import { Extensions as EditorInputExtensions, IEditorInputFactory, IEditorInputFactoryRegistry } from 'vs/workbench/common/editor'; +import { Extensions as EditorInputExtensions, IEditorInputFactory, IEditorInputFactoryRegistry, ActiveEditorContext } from 'vs/workbench/common/editor'; import * as SearchConstants from 'vs/workbench/contrib/search/common/constants'; import * as SearchEditorConstants from 'vs/workbench/contrib/searchEditor/browser/constants'; import { SearchEditor } from 'vs/workbench/contrib/searchEditor/browser/searchEditor'; -import { OpenResultsInEditorAction, OpenSearchEditorAction, toggleSearchEditorCaseSensitiveCommand, toggleSearchEditorContextLinesCommand, toggleSearchEditorRegexCommand, toggleSearchEditorWholeWordCommand, selectAllSearchEditorMatchesCommand } from 'vs/workbench/contrib/searchEditor/browser/searchEditorActions'; +import { OpenResultsInEditorAction, OpenSearchEditorAction, toggleSearchEditorCaseSensitiveCommand, toggleSearchEditorContextLinesCommand, toggleSearchEditorRegexCommand, toggleSearchEditorWholeWordCommand, selectAllSearchEditorMatchesCommand, RerunSearchEditorSearchAction } from 'vs/workbench/contrib/searchEditor/browser/searchEditorActions'; import { getOrMakeSearchEditorInput, SearchEditorInput } from 'vs/workbench/contrib/searchEditor/browser/searchEditorInput'; import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; import { CommandsRegistry } from 'vs/platform/commands/common/commands'; @@ -159,15 +159,6 @@ KeybindingsRegistry.registerCommandAndKeybindingRule({ handler: selectAllSearchEditorMatchesCommand }); -CommandsRegistry.registerCommand( - SearchEditorConstants.RerunSearchEditorSearchCommandId, - (accessor: ServicesAccessor) => { - const activeControl = accessor.get(IEditorService).activeControl; - if (activeControl instanceof SearchEditor) { - activeControl.triggerSearch({ resetCursor: false }); - } - }); - CommandsRegistry.registerCommand( SearchEditorConstants.CleanSearchEditorStateCommandId, (accessor: ServicesAccessor) => { @@ -191,4 +182,19 @@ registry.registerWorkbenchAction( registry.registerWorkbenchAction( SyncActionDescriptor.create(OpenSearchEditorAction, OpenSearchEditorAction.ID, OpenSearchEditorAction.LABEL), 'Search Editor: Open New Search Editor', category); + +registry.registerWorkbenchAction(SyncActionDescriptor.create(RerunSearchEditorSearchAction, RerunSearchEditorSearchAction.ID, RerunSearchEditorSearchAction.LABEL, + { mac: { primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KEY_R } }, ContextKeyExpr.and(SearchEditorConstants.InSearchEditor)), + 'Search Editor: Rerun', category); //#endregion + + +MenuRegistry.appendMenuItem(MenuId.EditorTitle, { + command: { + id: RerunSearchEditorSearchAction.ID, + title: RerunSearchEditorSearchAction.LABEL, + icon: { id: 'codicon/refresh' }, + }, + group: 'navigation', + when: ContextKeyExpr.and(ActiveEditorContext.isEqualTo(SearchEditorConstants.SearchEditorID)) +}); diff --git a/src/vs/workbench/contrib/searchEditor/browser/searchEditor.ts b/src/vs/workbench/contrib/searchEditor/browser/searchEditor.ts index a32b0f8fc23..523e97cdac5 100644 --- a/src/vs/workbench/contrib/searchEditor/browser/searchEditor.ts +++ b/src/vs/workbench/contrib/searchEditor/browser/searchEditor.ts @@ -35,7 +35,7 @@ import { InputBoxFocusedKey } from 'vs/workbench/contrib/search/common/constants import { ITextQueryBuilderOptions, QueryBuilder } from 'vs/workbench/contrib/search/common/queryBuilder'; import { getOutOfWorkspaceEditorResources } from 'vs/workbench/contrib/search/common/search'; import { SearchModel } from 'vs/workbench/contrib/search/common/searchModel'; -import { InSearchEditor, SearchEditorFindMatchClass } from 'vs/workbench/contrib/searchEditor/browser/constants'; +import { InSearchEditor, SearchEditorFindMatchClass, SearchEditorID } from 'vs/workbench/contrib/searchEditor/browser/constants'; import type { SearchConfiguration, SearchEditorInput } from 'vs/workbench/contrib/searchEditor/browser/searchEditorInput'; import { extractSearchQuery, serializeSearchConfiguration, serializeSearchResultForEditor } from 'vs/workbench/contrib/searchEditor/browser/searchEditorSerialization'; import { IPatternInfo, ISearchConfigurationProperties, ITextQuery } from 'vs/workbench/services/search/common/search'; @@ -56,7 +56,7 @@ const FILE_LINE_REGEX = /^(\S.*):$/; type SearchEditorViewState = ICodeEditorViewState & { focused: 'input' | 'editor' }; export class SearchEditor extends BaseTextEditor { - static readonly ID: string = 'workbench.editor.searchEditor'; + static readonly ID: string = SearchEditorID; static readonly SEARCH_EDITOR_VIEW_STATE_PREFERENCE_KEY = 'searchEditorViewState'; diff --git a/src/vs/workbench/contrib/searchEditor/browser/searchEditorActions.ts b/src/vs/workbench/contrib/searchEditor/browser/searchEditorActions.ts index 094acf25fd3..464d2bb6e51 100644 --- a/src/vs/workbench/contrib/searchEditor/browser/searchEditorActions.ts +++ b/src/vs/workbench/contrib/searchEditor/browser/searchEditorActions.ts @@ -116,6 +116,24 @@ export class OpenResultsInEditorAction extends Action { } } +export class RerunSearchEditorSearchAction extends Action { + static readonly ID: string = Constants.RerunSearchEditorSearchCommandId; + static readonly LABEL = localize('search.rerunSearchInEditor', "Search Again"); + + constructor(id: string, label: string, + @IEditorService private readonly editorService: IEditorService, + ) { + super(id, label, 'codicon-refresh'); + } + + async run() { + const input = this.editorService.activeEditor; + if (input instanceof SearchEditorInput) { + (this.editorService.activeControl as SearchEditor).triggerSearch({ resetCursor: false }); + } + } +} + const openNewSearchEditor = async (accessor: ServicesAccessor) => { const editorService = accessor.get(IEditorService); From 20c071dd266f2526db347819191979186c12ac17 Mon Sep 17 00:00:00 2001 From: SteVen Batten Date: Wed, 26 Feb 2020 16:17:46 -0800 Subject: [PATCH 13/74] fixes #91630 --- src/vs/workbench/browser/parts/compositeBar.ts | 15 ++++++++++++--- src/vs/workbench/browser/parts/panel/panelPart.ts | 3 ++- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/src/vs/workbench/browser/parts/compositeBar.ts b/src/vs/workbench/browser/parts/compositeBar.ts index f7f3e18a1b3..ab90e89569c 100644 --- a/src/vs/workbench/browser/parts/compositeBar.ts +++ b/src/vs/workbench/browser/parts/compositeBar.ts @@ -24,6 +24,7 @@ import { DraggedViewIdentifier } from 'vs/workbench/browser/parts/views/viewPane import { Registry } from 'vs/platform/registry/common/platform'; import { IViewContainersRegistry, Extensions as ViewContainerExtensions, ViewContainerLocation, IViewDescriptorService } from 'vs/workbench/common/views'; import { ICompositeDragAndDrop, CompositeDragAndDropData } from 'vs/base/parts/composite/browser/compositeDnd'; +import { IPaneComposite } from 'vs/workbench/common/panecomposite'; export interface ICompositeBarItem { id: string; @@ -38,7 +39,7 @@ export class CompositeDragAndDrop implements ICompositeDragAndDrop { constructor( private viewDescriptorService: IViewDescriptorService, private targetContainerLocation: ViewContainerLocation, - private openComposite: (id: string, focus?: boolean) => void, + private openComposite: (id: string, focus?: boolean) => Promise, private moveComposite: (from: string, to: string) => void, private getVisibleCompositeIds: () => string[] ) { } @@ -76,7 +77,11 @@ export class CompositeDragAndDrop implements ICompositeDragAndDrop { if (destinationContainer && !destinationContainer.rejectAddedViews) { if (this.targetContainerLocation === ViewContainerLocation.Sidebar) { this.viewDescriptorService.moveViewsToContainer([viewDescriptor], destinationContainer); - this.openComposite(targetCompositeId, true); + this.openComposite(targetCompositeId, true).then(composite => { + if (composite) { + composite.openView(viewDescriptor.id, true); + } + }); } else { this.viewDescriptorService.moveViewToLocation(viewDescriptor, this.targetContainerLocation); this.moveComposite(this.viewDescriptorService.getViewContainer(viewDescriptor.id)!.id, targetCompositeId); @@ -91,7 +96,11 @@ export class CompositeDragAndDrop implements ICompositeDragAndDrop { this.moveComposite(newCompositeId, targetId); } - this.openComposite(newCompositeId, true); + this.openComposite(newCompositeId, true).then(composite => { + if (composite) { + composite.openView(viewDescriptor.id, true); + } + }); } } } diff --git a/src/vs/workbench/browser/parts/panel/panelPart.ts b/src/vs/workbench/browser/parts/panel/panelPart.ts index e8126ec13e1..a73f42b53f0 100644 --- a/src/vs/workbench/browser/parts/panel/panelPart.ts +++ b/src/vs/workbench/browser/parts/panel/panelPart.ts @@ -36,6 +36,7 @@ import { IExtensionService } from 'vs/workbench/services/extensions/common/exten import { ViewContainer, IViewContainersRegistry, Extensions as ViewContainerExtensions, IViewDescriptorService, IViewDescriptorCollection, ViewContainerLocation } from 'vs/workbench/common/views'; import { MenuId } from 'vs/platform/actions/common/actions'; import { ViewMenuActions } from 'vs/workbench/browser/parts/views/viewMenuActions'; +import { IPaneComposite } from 'vs/workbench/common/panecomposite'; interface ICachedPanel { id: string; @@ -143,7 +144,7 @@ export class PanelPart extends CompositePart implements IPanelService { getDefaultCompositeId: () => this.panelRegistry.getDefaultPanelId(), hidePart: () => this.layoutService.setPanelHidden(true), dndHandler: new CompositeDragAndDrop(this.viewDescriptorService, ViewContainerLocation.Panel, - (id: string, focus?: boolean) => this.openPanel(id, focus), + (id: string, focus?: boolean) => this.openPanel(id, focus) as Promise, (from: string, to: string) => this.compositeBar.move(from, to), () => this.getPinnedPanels().map(p => p.id) ), From e63119f785ae89239ee85ad40d40bfc0a166e36a Mon Sep 17 00:00:00 2001 From: Pine Wu Date: Wed, 26 Feb 2020 16:24:15 -0800 Subject: [PATCH 14/74] Fix #90538 --- test/smoke/src/areas/css/css.test.ts | 43 ---------------------------- test/smoke/src/main.ts | 1 - 2 files changed, 44 deletions(-) delete mode 100644 test/smoke/src/areas/css/css.test.ts diff --git a/test/smoke/src/areas/css/css.test.ts b/test/smoke/src/areas/css/css.test.ts deleted file mode 100644 index aa6ccb9590b..00000000000 --- a/test/smoke/src/areas/css/css.test.ts +++ /dev/null @@ -1,43 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { Application, ProblemSeverity, Problems } from '../../../../automation'; - -export function setup() { - describe('CSS', () => { - it('verifies quick outline', async function () { - const app = this.app as Application; - await app.workbench.quickopen.openFile('style.css'); - - await app.workbench.quickopen.openQuickOutline(); - await app.workbench.quickopen.waitForQuickOpenElements(names => names.length === 2); - }); - - it('verifies warnings for the empty rule', async function () { - const app = this.app as Application; - await app.workbench.quickopen.openFile('style.css'); - await app.workbench.editor.waitForTypeInEditor('style.css', '.foo{}'); - - await app.code.waitForElement(Problems.getSelectorInEditor(ProblemSeverity.WARNING)); - - await app.workbench.problems.showProblemsView(); - await app.code.waitForElement(Problems.getSelectorInProblemsView(ProblemSeverity.WARNING)); - await app.workbench.problems.hideProblemsView(); - }); - - it('verifies that warning becomes an error once setting changed', async function () { - const app = this.app as Application; - await app.workbench.settingsEditor.addUserSetting('css.lint.emptyRules', '"error"'); - await app.workbench.quickopen.openFile('style.css'); - - await app.code.waitForElement(Problems.getSelectorInEditor(ProblemSeverity.ERROR)); - - const problems = new Problems(app.code); - await problems.showProblemsView(); - await app.code.waitForElement(Problems.getSelectorInProblemsView(ProblemSeverity.ERROR)); - await problems.hideProblemsView(); - }); - }); -} diff --git a/test/smoke/src/main.ts b/test/smoke/src/main.ts index a1273ba379d..a7eec01dacc 100644 --- a/test/smoke/src/main.ts +++ b/test/smoke/src/main.ts @@ -25,7 +25,6 @@ import { setup as setupDataMigrationTests } from './areas/workbench/data-migrati import { setup as setupDataLossTests } from './areas/workbench/data-loss.test'; import { setup as setupDataPreferencesTests } from './areas/preferences/preferences.test'; import { setup as setupDataSearchTests } from './areas/search/search.test'; -import { setup as setupDataCSSTests } from './areas/css/css.test'; import { setup as setupDataEditorTests } from './areas/editor/editor.test'; import { setup as setupDataStatusbarTests } from './areas/statusbar/statusbar.test'; import { setup as setupDataExtensionTests } from './areas/extensions/extensions.test'; From 8510f53b59582cccc267c335150b518ae2a97a63 Mon Sep 17 00:00:00 2001 From: SteVen Batten Date: Wed, 26 Feb 2020 16:24:51 -0800 Subject: [PATCH 15/74] refs #91630 --- src/vs/workbench/browser/parts/compositeBar.ts | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/browser/parts/compositeBar.ts b/src/vs/workbench/browser/parts/compositeBar.ts index ab90e89569c..9598c3c1c32 100644 --- a/src/vs/workbench/browser/parts/compositeBar.ts +++ b/src/vs/workbench/browser/parts/compositeBar.ts @@ -54,8 +54,13 @@ export class CompositeDragAndDrop implements ICompositeDragAndDrop { if (currentLocation !== this.targetContainerLocation && this.targetContainerLocation !== ViewContainerLocation.Panel) { const destinationContainer = viewContainerRegistry.get(targetCompositeId); if (destinationContainer && !destinationContainer.rejectAddedViews) { - this.viewDescriptorService.moveViewsToContainer(this.viewDescriptorService.getViewDescriptors(currentContainer)!.allViewDescriptors.filter(vd => vd.canMoveView), destinationContainer); - this.openComposite(targetCompositeId, true); + const viewsToMove = this.viewDescriptorService.getViewDescriptors(currentContainer)!.allViewDescriptors.filter(vd => vd.canMoveView); + this.viewDescriptorService.moveViewsToContainer(viewsToMove, destinationContainer); + this.openComposite(targetCompositeId, true).then(composite => { + if (composite && viewsToMove.length === 1) { + composite.openView(viewsToMove[0].id, true); + } + }); } } else { this.moveComposite(dragData.id, targetCompositeId); From 7f1f3981cef74c2fd41b864ddecdb506579723be Mon Sep 17 00:00:00 2001 From: Jackson Kearl Date: Wed, 26 Feb 2020 16:32:24 -0800 Subject: [PATCH 16/74] Flip result/file counts. --- .../contrib/searchEditor/browser/searchEditorSerialization.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/searchEditor/browser/searchEditorSerialization.ts b/src/vs/workbench/contrib/searchEditor/browser/searchEditorSerialization.ts index 389faee3931..038519308e4 100644 --- a/src/vs/workbench/contrib/searchEditor/browser/searchEditorSerialization.ts +++ b/src/vs/workbench/contrib/searchEditor/browser/searchEditorSerialization.ts @@ -216,7 +216,7 @@ export const serializeSearchResultForEditor = const info = [ searchResult.count() - ? `${filecount} - ${resultcount}` + ? `${resultcount} - ${filecount}` : localize('noResults', "No Results"), '']; From b8de1ad5264ef1f7b8e0f56caa026becac39bbd5 Mon Sep 17 00:00:00 2001 From: Pine Wu Date: Wed, 26 Feb 2020 16:44:48 -0800 Subject: [PATCH 17/74] Fix #91300 --- src/vs/editor/contrib/suggest/media/suggest.css | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/vs/editor/contrib/suggest/media/suggest.css b/src/vs/editor/contrib/suggest/media/suggest.css index 821cb7d2623..875769452fa 100644 --- a/src/vs/editor/contrib/suggest/media/suggest.css +++ b/src/vs/editor/contrib/suggest/media/suggest.css @@ -392,6 +392,10 @@ word-wrap: break-word; } +.monaco-editor .suggest-widget .details > .monaco-scrollable-element > .body > .docs.markdown-docs .codicon { + vertical-align: sub; +} + .monaco-editor .suggest-widget .details > .monaco-scrollable-element > .body > p:empty { display: none; } From 3c1e64220f137f9f4710841022b9d58e654e9f01 Mon Sep 17 00:00:00 2001 From: Rachel Macfarlane Date: Wed, 26 Feb 2020 17:13:11 -0800 Subject: [PATCH 18/74] Fixes #91384 --- .../electron-browser/processExplorer/processExplorerMain.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/vs/code/electron-browser/processExplorer/processExplorerMain.ts b/src/vs/code/electron-browser/processExplorer/processExplorerMain.ts index 09ccca9b823..9684cbd4c20 100644 --- a/src/vs/code/electron-browser/processExplorer/processExplorerMain.ts +++ b/src/vs/code/electron-browser/processExplorer/processExplorerMain.ts @@ -75,7 +75,11 @@ function getProcessItem(processes: FormattedProcessItem[], item: ProcessItem, in // Recurse into children if any if (Array.isArray(item.children)) { - item.children.forEach(child => getProcessItem(processes, child, indent + 1, isLocal)); + item.children.forEach(child => { + if (child) { + getProcessItem(processes, child, indent + 1, isLocal); + } + }); } } From db380eaad006fec0c7a205ed33a0fc50ada6a723 Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Wed, 26 Feb 2020 17:29:55 -0800 Subject: [PATCH 19/74] Fix build --- test/smoke/src/main.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/test/smoke/src/main.ts b/test/smoke/src/main.ts index a7eec01dacc..fc1f4e5569f 100644 --- a/test/smoke/src/main.ts +++ b/test/smoke/src/main.ts @@ -301,7 +301,6 @@ describe(`VSCode Smoke Tests (${opts.web ? 'Web' : 'Electron'})`, () => { if (!opts.web) { setupDataLossTests(); } if (!opts.web) { setupDataPreferencesTests(); } setupDataSearchTests(); - setupDataCSSTests(); setupDataEditorTests(); setupDataStatusbarTests(!!opts.web); if (!opts.web) { setupDataExtensionTests(); } From 61538b5e3e2674e449a28e328210fb5030435fc3 Mon Sep 17 00:00:00 2001 From: SteVen Batten Date: Wed, 26 Feb 2020 17:34:34 -0800 Subject: [PATCH 20/74] only set drop target background for valid tgt --- src/vs/base/parts/composite/browser/compositeDnd.ts | 1 + src/vs/workbench/browser/parts/compositeBar.ts | 10 ++++++++-- src/vs/workbench/browser/parts/compositeBarActions.ts | 6 ++++-- 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/src/vs/base/parts/composite/browser/compositeDnd.ts b/src/vs/base/parts/composite/browser/compositeDnd.ts index ca8b52d491a..6091c8a10d3 100644 --- a/src/vs/base/parts/composite/browser/compositeDnd.ts +++ b/src/vs/base/parts/composite/browser/compositeDnd.ts @@ -21,4 +21,5 @@ export class CompositeDragAndDropData implements IDragAndDropData { export interface ICompositeDragAndDrop { drop(data: IDragAndDropData, target: string | undefined, originalEvent: DragEvent): void; onDragOver(data: IDragAndDropData, target: string | undefined, originalEvent: DragEvent): boolean; + onDragEnter(data: IDragAndDropData, target: string | undefined, originalEvent: DragEvent): boolean; } diff --git a/src/vs/workbench/browser/parts/compositeBar.ts b/src/vs/workbench/browser/parts/compositeBar.ts index 9598c3c1c32..a77472da253 100644 --- a/src/vs/workbench/browser/parts/compositeBar.ts +++ b/src/vs/workbench/browser/parts/compositeBar.ts @@ -111,7 +111,15 @@ export class CompositeDragAndDrop implements ICompositeDragAndDrop { } } + onDragEnter(data: CompositeDragAndDropData, targetCompositeId: string | undefined, originalEvent: DragEvent): boolean { + return this.canDrop(data, targetCompositeId); + } + onDragOver(data: CompositeDragAndDropData, targetCompositeId: string | undefined, originalEvent: DragEvent): boolean { + return this.canDrop(data, targetCompositeId); + } + + private canDrop(data: CompositeDragAndDropData, targetCompositeId: string | undefined): boolean { const dragData = data.getData(); const viewContainerRegistry = Registry.as(ViewContainerExtensions.ViewContainersRegistry); @@ -173,8 +181,6 @@ export class CompositeDragAndDrop implements ICompositeDragAndDrop { const destinationContainer = viewContainerRegistry.get(targetCompositeId); return !!destinationContainer && !destinationContainer.rejectAddedViews; } - - return false; } } diff --git a/src/vs/workbench/browser/parts/compositeBarActions.ts b/src/vs/workbench/browser/parts/compositeBarActions.ts index c4eb0fbc8ed..399b868395a 100644 --- a/src/vs/workbench/browser/parts/compositeBarActions.ts +++ b/src/vs/workbench/browser/parts/compositeBarActions.ts @@ -544,14 +544,16 @@ export class CompositeActionViewItem extends ActivityActionViewItem { if (this.compositeTransfer.hasData(DraggedCompositeIdentifier.prototype)) { const data = this.compositeTransfer.getData(DraggedCompositeIdentifier.prototype); if (Array.isArray(data) && data[0].id !== this.activity.id) { - this.updateFromDragging(container, true); + const validDropTarget = this.dndHandler.onDragOver(new CompositeDragAndDropData('composite', data[0].id), this.activity.id, e); + this.updateFromDragging(container, validDropTarget); } } if (this.compositeTransfer.hasData(DraggedViewIdentifier.prototype)) { const data = this.compositeTransfer.getData(DraggedViewIdentifier.prototype); if (Array.isArray(data) && data[0].id !== this.activity.id) { - this.updateFromDragging(container, true); + const validDropTarget = this.dndHandler.onDragOver(new CompositeDragAndDropData('view', data[0].id), this.activity.id, e); + this.updateFromDragging(container, validDropTarget); } } }, From 6f15da251fffbc5a45fafa3971d9aa06d7ff7773 Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Wed, 26 Feb 2020 17:36:35 -0800 Subject: [PATCH 21/74] Only add new separator when SyncSettingAction is present --- .../workbench/contrib/preferences/browser/settingsTree.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/contrib/preferences/browser/settingsTree.ts b/src/vs/workbench/contrib/preferences/browser/settingsTree.ts index dedf95bbe56..bae1aee1cd5 100644 --- a/src/vs/workbench/contrib/preferences/browser/settingsTree.ts +++ b/src/vs/workbench/contrib/preferences/browser/settingsTree.ts @@ -1205,7 +1205,6 @@ export class SettingTreeRenderers { new Separator(), this._instantiationService.createInstance(CopySettingIdAction), this._instantiationService.createInstance(CopySettingAsJSONAction), - new Separator(), ]; const actionFactory = (setting: ISetting) => this.getActionsForSetting(setting); @@ -1239,7 +1238,10 @@ export class SettingTreeRenderers { private getActionsForSetting(setting: ISetting): IAction[] { const enableSync = this._userDataSyncEnablementService.isEnabled(); return enableSync && !setting.disallowSyncIgnore ? - [this._instantiationService.createInstance(SyncSettingAction, setting)] : + [ + new Separator(), + this._instantiationService.createInstance(SyncSettingAction, setting) + ] : []; } From 8c168ae86df8f1d1578a0ca9aa720219e0661cca Mon Sep 17 00:00:00 2001 From: Pine Wu Date: Wed, 26 Feb 2020 17:47:06 -0800 Subject: [PATCH 22/74] Fix #89933 --- src/vs/workbench/contrib/markers/browser/markersTreeViewer.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/markers/browser/markersTreeViewer.ts b/src/vs/workbench/contrib/markers/browser/markersTreeViewer.ts index abd5d1d00fe..fd2523ba4d9 100644 --- a/src/vs/workbench/contrib/markers/browser/markersTreeViewer.ts +++ b/src/vs/workbench/contrib/markers/browser/markersTreeViewer.ts @@ -856,6 +856,7 @@ export class ResourceDragAndDrop implements ITreeDragAndDrop { registerThemingParticipant((theme, collector) => { const linkFg = theme.getColor(textLinkForeground); if (linkFg) { - collector.addRule(`.markers-panel .markers-panel-container .tree-container .monaco-tl-contents .details-container a.code-link span:hover { color: ${linkFg}; }`); + collector.addRule(`.markers-panel .markers-panel-container .tree-container .monaco-tl-contents .details-container a.code-link .marker-code > span:hover { color: ${linkFg}; }`); + collector.addRule(`.markers-panel .markers-panel-container .tree-container .monaco-list:focus .monaco-tl-contents .details-container a.code-link .marker-code > span:hover { color: ${linkFg.lighten(.4)}; }`); } }); From 0eebaf9ad23748baca2afc0da425650922bc23de Mon Sep 17 00:00:00 2001 From: Miguel Solorio Date: Wed, 26 Feb 2020 19:55:11 -0800 Subject: [PATCH 23/74] Update Codicons: add bell-progress (ref #91469) --- .../ui/codiconLabel/codicon/codicon.css | 7 ++++--- .../ui/codiconLabel/codicon/codicon.ttf | Bin 57012 -> 57380 bytes 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/vs/base/browser/ui/codiconLabel/codicon/codicon.css b/src/vs/base/browser/ui/codiconLabel/codicon/codicon.css index 41efce5c63d..b71ef2dafa5 100644 --- a/src/vs/base/browser/ui/codiconLabel/codicon/codicon.css +++ b/src/vs/base/browser/ui/codiconLabel/codicon/codicon.css @@ -5,7 +5,7 @@ @font-face { font-family: "codicon"; - src: url("./codicon.ttf?279add2ec8b3d516ca20a123230cbf9f") format("truetype"); + src: url("./codicon.ttf?b5dd8f5aa953889dc1f4c9fa9b44d3dd") format("truetype"); } .codicon[class*='codicon-'] { @@ -415,5 +415,6 @@ .codicon-group-by-ref-type:before { content: "\eb97" } .codicon-ungroup-by-ref-type:before { content: "\eb98" } .codicon-bell-dot:before { content: "\f101" } -.codicon-debug-alt-2:before { content: "\f102" } -.codicon-debug-alt:before { content: "\f103" } +.codicon-bell-progress:before { content: "\f102" } +.codicon-debug-alt-2:before { content: "\f103" } +.codicon-debug-alt:before { content: "\f104" } diff --git a/src/vs/base/browser/ui/codiconLabel/codicon/codicon.ttf b/src/vs/base/browser/ui/codiconLabel/codicon/codicon.ttf index df86f7d4d9a21847df1652c1782ecf6f8aa0eddb..845205f5b3a4132caa8bdf4b586532cfb8a1cd19 100644 GIT binary patch delta 5308 zcmYM%33$}ixd!m}WI{HwlYN~mBq1aOLYP1d5JG?uAjBX6sUkZO6G1>kLD#{Fx49sA3^1Djw9W0Dy~Le7a~cSH9Y|ciu;cCp9}Spx6v*5KbeFZypFJ-vEaw1U z%hw>#&L_hE*ejj)_fcVc=kk@i{k#Wr76?7wv3Tz6&fF*Y{poc;NJr=Fl}kce@D{(G z#uxc-pWQh>@1=}U_W|#n;0vObEMB(!!Do}IfcN)_o?q=K8`?$_bmVMd(4oo9P_FP-F?)Y4ShT$w5unq&yWk( zej-B7!*}go8EX{ayMWLT?{mcSzYnk*>?Zq;Yj&I6wu_-%Ux!r(e~7=}Bp$#KlZ0R4 zGIrw&RGD%(T*PNsgd)6++1P>~qulgC8)8fumSZmdh+p7!ykWBNDDK5~5ilW`ZxZnp zo-z^m+C-TI6K%rqkTE8f@5zTy^g3 z6=}#s7P66pT=ir?O2Q@xC2YE40mD$?!rpkja9e@ ztFZ<_tmSL&!#doL2eBR-un`Yq6CS~4Jch^7g(t8T-^VsQiKp;CcpCqUAK)20i|zOk zUc^h-iCy>!UdB)H3cAsQpJ5MPtHECUoJ;LZ{1W?d0KdjT{D#Zv5Z=MN_$?0OJ-m;j zIELTh_c)F}-~*h%pYUg#>iQ%iJ!tU>KE(z66PNHWe2y#lH~xb!@eRJkRRiNQp{AD! zH<6~di7{~|*`%0MlV;LQhRHP9CdcF&zsWQCrqJ{?MW)!4n0}_z^fv=cg&AlDnMyO* zRN*;1j~B25qfn2Dn1p7GG4Ys?gBFZOIx_Go7UDL1&lDgQakvh(T&ZEtKO4y<0bXkU zi{0kk^65a=D^aOjc(8MXOAvOha52Kp6D~{G`GO;?3xrD*cA;?5!nO;SFYK+tg$%n$ zxTIlk6L2Tm4j|~=aGk?;3RgVr?ZUMWyI8mjV3!E@1MD5bodLU4xJO`@33m(Za^b## zy;Hb@U{?srxt{D@d_de*uq%Zd4EAn84C^Z4rh~mlxcy*P3pXO{y}~UCyGFPN~p18AN9~1;w*9&($toJp7cZoKLce(9GVK0Dv zShy!(HwpU#?9JXUBz(=fSqxj2eN0RO>*HdgS-XTS1=jns5*}iGLX2VEDkiqeAMb_D8~g1pA_}Gr_(j>`|~gh209)yQsvz1-nbw!C-&l ztuWrOnZdp+Y-_MT6*f57SA?w&_ElligY6c!KiJ*EMhM#@Y>BWx6E;WKJpw=LYr=-f z73N)eV(*0Yt~{}e!tNFJQ`nyiJ1guyVULAcOAV}pkMwXjvg9uzih*xv}-H|$%&Mh^S7u%*Ku5;k|(cZ6*o_OP(w!@ehM{jf)b zLx9Wweclk~0qjxXWPm*;oDs0U6HW`*-wWpk>~Y})f&GJUmcV`>oGP&1ek0Bo*b~A@ z1N$cla_GRG6pkO*KMMyD>?z?$g8hqdIKh4>98<7=6%H)e)56gO`#0ebgFPdd#rk*Q zV1qsDUH`Luck}q*AA$v}=Y(Sq_9Ni{ggq}Dg|HtB2Og{yjz?H09F(x12uCLDr^4Y0 zdqJ?2*WdnAI8k9g6V6uHi^3@jdr3HNVgDtZys(#rGZ^-B;WUQ5BAm;x{}xVY*e`^$ z8umXF_XH%J)u;3|co4{oq9{=roVgCN`xVI+hL2*V*jfXOj`r~Sjc3^tP=(2StkiTW(_v;hG1D+glQS> zdSPycYZWGFxGBOc4R?buRl`jc=4-e%VbX@1Cd}M$(}n39?nVhRh{MegMsm3C2*Wwt zO~RNCceCIs>r63x-|iMMKGs=cLRn{v>BTxnOgQUYF_El1+ITlGUc;C#CWdu^m^jvj zVvD@Sp~_S$JfFdt7*UgXM}(oe;aq z(({5ReO0~%z5~9qp(UXQLeKV^+3Q5uj_|eN=fl5^m>4l9Vr9f55!)l)iZ~TvBV!|L zBNs*XL{&z$M;+)L(mSj7y58rbW25V%S4HoQJ`*!5W^GJ&%>LNs*nM&NaoggK#$Abz zkI#>x{D|JWe>9nG>jcF&+8`ED*KbKLLu{Sd+ zb7tm_ti-J5taVx2vn#XPvR7q4oqZ{1K+e3J4|6x=p7xje_vAI_eVIQZ|4PBW!sf!Q zg*yu`_s!}%r*H6ZQEX9N(IZ8di%W~w6@OS#S+cgIr(blxBc-9GD@xDyZ|J|Fe|MR` zthVf?^62uC@|N-q<(CKSsEDW-QL(6EbH(0@3j^m2Ts?5tz)ORM4q7#+XOOMTs%))% zs`A~z(+9s&)l>D^kXb_x1`tRJGzGQ!}@BJH7Vw@XF!4Mr4dwGUD(^jI15Gy)L$HWnFjOsZm*@7LD36>TrEj{qp+P zN0*G=G5S)&s)l_H-;P-{X3yBb*coG2kJ~iv-Erp{6B`4K9gTa&cZ}aU{zQ|%sj+Ew z)Apt_6JDHfZerHN_K9026;7HnY4XYDu;zy5LzBZMw@ltP*|sFL%xl@&(tUl>^~+mJ zTRU3Uv~F&FuC-@M&XfgHelg|J4UIP(oti&&`qZbVo^PvZo7MI}+rhRkrmdRx^z`M^ z58arudt2tMp~+!fc<}A??c}Mhktu!#b8u%@eD3(d)Ie2ncuG=uadlBxcxs?BwO3Vj zYFJWgc+rs5@RZ8x;;{VUuDQ9R^VVnh{Z+}y2?-TTD++Qa=3YfEA6EJ2|M!Wm?%eu< zjQ>7*JHv0h7qkz%_UeL)Ve2w-y(iG^f8k{_WcQ9E?I9r{fv(tNKaP!=Gryywe96+q Q3zyDcwruws$G(dGKW`nJnE(I) delta 5119 zcmYM%4Sde!9tQC1-ZR_meY1_d7_%8>#%3F4W|+Ls`%8K=FKfwLXd(3=m9%PENu7?< zk)%=yITDhjbV^G?l2nrJTSBG6;aq>$`Fswa@ALaVvw5Cp|NH*^u6y-P-=^)p+H`+C zU}^x2nlQCu#-UwtF9JcEfY>>=PMKTTYf#M!Aeq)5ubNabvGK22oB6%Rsj!M)2tL%H z39q+NM%C2Wb6)SvE0_~NVEvTo6Dqp+!}+s`*+9VLsTFf(1PsO={=4@x&8JmNos{-c zQjdke$8-1%p);n>n*Dg*=)J(c#Xxks$G4?-&xi5;L%_bYJN1^R;@=VGJLSE`ky$hU z_WOq@olU(Cj#rX1T`u+eeJ(Pz)AS7U1hU|0>0A- z4A{yaisoM*Uu=o3v3p&)t92{R`IZHD@~^~Ee2M$;iD`tL_!S%Q2RfQ;Se(T#xD74& zxyGRmFC*K;Vk9C=Tg<|E9K?3~3tLPw9>sh-fC6JM(Zt{)o;Ja_WEz@i6J{DVxC`nP`R9XoD=Y zMLXo6Jvty4dB{g0I-xVVpf|2VAM`^xhF~a$VK_!$6h>nVuE$v1fE#fWZpJOBzywUf zt*FB7n1ZR8hUu7rJ1`ToaVM&A7v^9t=HYJKgL~oU_bk9dKNevz?#F|82utxW9>HU% z#p76pC-5Ye<0-7b(|87d!?XB1{(8n0~@gkZ(=jv!dAS^ zb+rTU;9cy(d)STl@c}->UVMaq<74c@r>Mtg*pJU~0AXL?5Dw!AzQWgaXF?MF4yW-m z&fpx*<2U?{3-}X%;WGY%E4XR`jL!s`AQNIjO}L3PaVFj*n8v1wNi<0&#WXdkrkQDO z(oDL^FfC1{X=PfQHYUroGdZTc>0okAp6Q5xVii{71(c!(24Eltq0B^~KL#hDFPb0` z>rsixs4*=Ni6V5}_*}yX|iGd7a;6J;ZlU1B>052 zQn)-}Zxt?7*ecjH+yk(8 z2zLYQO!4-+oh95Mu(P>j_yBGe*gJ*W2DVz@z3^Satpv;7;Nhl%ohyi7ohRIAuy+f$ z9PE7I=7YUQxD8?N6>RtO;(xd|VHXItur3ttSJ*|uoeS&zx`}%jmd(k--3)ubz`K>+ zbK(w%eNf=tt|h`<54)87d|(5BeOS0LV7VqdYznZC2`;hLifPFDxR_|xWn#iuz279U zjle!3@Lu#u;roGIE^IQWYaQ{3KZ?(v7xp~Z)xtgl`+~6Jz^)PY9@rO!T?lrquphBC z3p*36cPEKG3icIYw}M?K>|3y}0)Fp-Ee!TGVKak$UD(!O*9#jQ>>Gk4)(ryh4s8^q zuySU3(3JH}K`QHJK{HnGZWEe&YtXyhgf!N-1T9!O2Ruk;eOr*hx=oPDx?R|FVRs0- zFYG(QJ`B54*pXr174~M>T^_DKwrSY+gbf>Zx3G1?zAtRzuzQ5<9QFfYV~71v*y3UL z3Y$Ib$HKM``-yM>!0r={0+1@@3|%D^5L&KuY-#m~_Ldqg;dV80TMBiN(D!36uYa74i#6AmlbZ-iqD_PB6> z!G0?oWw74~hZ^kn!tn-s!n^+`_~|F`$q&Mr2YXUD{a}9-&Oz8y!ifm`lW^|ATH%z0 zb;5ZGds;X-VSg6RP}nnqJ9z)?FT%kJdsaANVb2MNE$n&W*oFO7IDlb)6OLlo--SaN z_JVLc!~P*0)UbaFM>gzVF9i0IT>E5~c}-Zr`X9kU)+@qs4|`QO_`wf< z4I==Y5rzS{0AVbE^9ch2{4S7Bh*<%yfiN||1qt&5T(B@nz=a4i1zba6x_}E6<_x$n zVd8)b7iJH*2w@6=i@b&(cLgt^#OuH=S{PE`VuW!8E>;*^;2H@d3|yQr%)rG9o?}fA z1{}D?!l(n+L>PMD68ZWrk)M7oYmzVt!6geb5nPHe9lve)}S^EgSW9=*Wp0%Ig1Z#i653B-@!;KauZ@4kS3=Vg_ z_!-CH#tMTu+zrBr4tJw4ti#A|`-!oERT#g_uCr@nV8lCx{7Qo#@^F ziA+qPd@@N)IBTVtNY-1$#IaV1iD$h{OakjmpW zF-=)#h)HF=LrgQ)nPQr=&JvTxI$KOS>z!gUSgXafWW7sFChHtAtyt%hpAV)rFXoA9 z!+N)vEY|sAynTC*m>kx7#dzD+`w(QjZM#5BF6%-ud8~_sXC=7%gr_F%|HXVlJV3$S zFFZ=YJs><(!96G_WnCgXXu&-sJaWM;6&}9e9u^+M;A#YAtd9tfW^j*Q!?)d^7mo=B zv(^d^Zg9(lM>x1T;b9K$3E{C0?n&VR4{o{es0a6yzrfS?T9-OpAtVLeop+__`?Z73Du3!xTx`h#wVKOHCdGykXV}d zOj2CZ#H20BNS>0sHu-4sm6V#4^(hBZE;Jq3bV<`4shv|#HY;kjxOsH*wP_>LR$|q$ZRfRJ-ga|#W%i=%m$ScXSDu5M@i{AUcIVjkaqauI-`4(MhoBAvJ1pyPAU86% zEVnv$UG8sr8F?EzhUQ1+_s`#2kXkUdU|PZIf-{9Vh5ZZX6|U^mqElt3i=8Vw*ZaGa zby?hHT~T;ZPEm2!$gWGfZYVA)uIU!kZFaYhN-|5vmMky1(!Hwt{?hQ$!qV!}-KA%G zWcHZYV_(nMo{M^+*T7x}$`Z=Plv-MhB;rrrmyJJ~0rPidbieQNvc=^Nd5Pv5is z^7_r|x2oU4epmVz4+t1gI-q*Mt^sET-aByHp!`9D#|>Ip-lBY5`OD?!2bT?=Hh9P2 zvqQp%OdGOq=;EP!h8`Yjhh82QIc(0box__9A2@u~h^!IwM{F2zVPwydPmJ6;^4O@< vQNu Date: Thu, 27 Feb 2020 08:05:36 +0100 Subject: [PATCH 24/74] Fix #91576 --- 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 3399c0adb64..3769fabc22a 100644 --- a/src/vs/workbench/contrib/userDataSync/browser/userDataSync.ts +++ b/src/vs/workbench/contrib/userDataSync/browser/userDataSync.ts @@ -522,7 +522,7 @@ export class UserDataSyncWorkbenchContribution extends Disposable implements IWo quickPick.ok = false; quickPick.customButton = true; if (this.authenticationState.get() === AuthStatus.SignedIn) { - quickPick.customLabel = localize('turn on', "Turn on"); + quickPick.customLabel = localize('turn on', "Turn On"); } else { const displayName = this.authenticationService.getDisplayName(this.userDataSyncStore!.authenticationProviderId); quickPick.description = localize('sign in and turn on sync detail', "Sign in with your {0} account to synchronize your data across devices.", displayName); @@ -680,7 +680,7 @@ export class UserDataSyncWorkbenchContribution extends Disposable implements IWo type: 'info', message: localize('turn off sync confirmation', "Turn off Sync"), detail: localize('turn off sync detail', "Your settings, keybindings, extensions and UI State will no longer be synced."), - primaryButton: localize('turn off', "Turn off"), + primaryButton: localize('turn off', "Turn Off"), checkbox: { label: localize('turn off sync everywhere', "Turn off sync on all your devices and clear the data from the cloud.") } From b8f6178bea672f076decaef65b7b1a5739d3576a Mon Sep 17 00:00:00 2001 From: SteVen Batten Date: Wed, 26 Feb 2020 23:11:29 -0800 Subject: [PATCH 25/74] improve feedback for composite excess area --- .../activitybar/media/activitybarpart.css | 4 + .../workbench/browser/parts/compositeBar.ts | 140 ++++++++++++------ .../browser/parts/compositeBarActions.ts | 4 +- .../browser/parts/panel/media/panelpart.css | 4 + 4 files changed, 105 insertions(+), 47 deletions(-) diff --git a/src/vs/workbench/browser/parts/activitybar/media/activitybarpart.css b/src/vs/workbench/browser/parts/activitybar/media/activitybarpart.css index cbc3d14705b..6e3ff5bf0f4 100644 --- a/src/vs/workbench/browser/parts/activitybar/media/activitybarpart.css +++ b/src/vs/workbench/browser/parts/activitybar/media/activitybarpart.css @@ -27,6 +27,10 @@ margin-bottom: auto; } +.monaco-workbench .activitybar > .content > .composite-bar-excess { + height: 100%; +} + .monaco-workbench .activitybar .menubar { width: 100%; height: 35px; diff --git a/src/vs/workbench/browser/parts/compositeBar.ts b/src/vs/workbench/browser/parts/compositeBar.ts index a77472da253..93102067fa2 100644 --- a/src/vs/workbench/browser/parts/compositeBar.ts +++ b/src/vs/workbench/browser/parts/compositeBar.ts @@ -17,8 +17,8 @@ import { StandardMouseEvent } from 'vs/base/browser/mouseEvent'; import { IContextMenuService } from 'vs/platform/contextview/browser/contextView'; import { Widget } from 'vs/base/browser/ui/widget'; import { isUndefinedOrNull } from 'vs/base/common/types'; -import { LocalSelectionTransfer } from 'vs/workbench/browser/dnd'; -import { ITheme } from 'vs/platform/theme/common/themeService'; +import { LocalSelectionTransfer, DragAndDropObserver } from 'vs/workbench/browser/dnd'; +import { ITheme, IThemeService } from 'vs/platform/theme/common/themeService'; import { Emitter } from 'vs/base/common/event'; import { DraggedViewIdentifier } from 'vs/workbench/browser/parts/views/viewPaneContainer'; import { Registry } from 'vs/platform/registry/common/platform'; @@ -222,6 +222,7 @@ export class CompositeBar extends Widget implements ICompositeBar { constructor( items: ICompositeBarItem[], private options: ICompositeBarOptions, + @IThemeService private readonly themeService: IThemeService, @IInstantiationService private readonly instantiationService: IInstantiationService, @IContextMenuService private readonly contextMenuService: IContextMenuService ) { @@ -250,6 +251,7 @@ export class CompositeBar extends Widget implements ICompositeBar { create(parent: HTMLElement): HTMLElement { const actionBarDiv = parent.appendChild($('.composite-bar')); + const excessDiv = parent.appendChild($('.composite-bar-excess')); this.compositeSwitcherBar = this._register(new ActionBar(actionBarDiv, { actionViewItemProvider: (action: IAction) => { @@ -276,58 +278,99 @@ export class CompositeBar extends Widget implements ICompositeBar { this._register(addDisposableListener(parent, EventType.CONTEXT_MENU, e => this.showContextMenu(e))); // Allow to drop at the end to move composites to the end - this._register(addDisposableListener(parent, EventType.DROP, (e: DragEvent) => { - if (this.compositeTransfer.hasData(DraggedCompositeIdentifier.prototype)) { - EventHelper.stop(e, true); + this._register(new DragAndDropObserver(excessDiv, { + onDragOver: (e: DragEvent) => { + if (this.compositeTransfer.hasData(DraggedCompositeIdentifier.prototype)) { + EventHelper.stop(e, true); - const data = this.compositeTransfer.getData(DraggedCompositeIdentifier.prototype); - if (Array.isArray(data)) { - const draggedCompositeId = data[0].id; - this.compositeTransfer.clearData(DraggedCompositeIdentifier.prototype); + const data = this.compositeTransfer.getData(DraggedCompositeIdentifier.prototype); + if (Array.isArray(data)) { + const draggedCompositeId = data[0].id; - this.options.dndHandler.drop(new CompositeDragAndDropData('composite', draggedCompositeId), undefined, e); - } - } - - if (this.compositeTransfer.hasData(DraggedViewIdentifier.prototype)) { - const data = this.compositeTransfer.getData(DraggedViewIdentifier.prototype); - if (Array.isArray(data)) { - const draggedViewId = data[0].id; - this.compositeTransfer.clearData(DraggedViewIdentifier.prototype); - - this.options.dndHandler.drop(new CompositeDragAndDropData('view', draggedViewId), undefined, e); - } - } - })); - - this._register(addDisposableListener(parent, EventType.DRAG_OVER, (e: DragEvent) => { - if (this.compositeTransfer.hasData(DraggedCompositeIdentifier.prototype)) { - EventHelper.stop(e, true); - - const data = this.compositeTransfer.getData(DraggedCompositeIdentifier.prototype); - if (Array.isArray(data)) { - const draggedCompositeId = data[0].id; - - // Check if drop is allowed - if (e.dataTransfer && !this.options.dndHandler.onDragOver(new CompositeDragAndDropData('composite', draggedCompositeId), undefined, e)) { - e.dataTransfer.dropEffect = 'none'; + // Check if drop is allowed + if (e.dataTransfer && !this.options.dndHandler.onDragOver(new CompositeDragAndDropData('composite', draggedCompositeId), undefined, e)) { + e.dataTransfer.dropEffect = 'none'; + } } } - } - if (this.compositeTransfer.hasData(DraggedViewIdentifier.prototype)) { - EventHelper.stop(e, true); + if (this.compositeTransfer.hasData(DraggedViewIdentifier.prototype)) { + EventHelper.stop(e, true); - const data = this.compositeTransfer.getData(DraggedViewIdentifier.prototype); - if (Array.isArray(data)) { - const draggedViewId = data[0].id; + const data = this.compositeTransfer.getData(DraggedViewIdentifier.prototype); + if (Array.isArray(data)) { + const draggedViewId = data[0].id; - // Check if drop is allowed - if (e.dataTransfer && !this.options.dndHandler.onDragOver(new CompositeDragAndDropData('view', draggedViewId), undefined, e)) { - e.dataTransfer.dropEffect = 'none'; + // Check if drop is allowed + if (e.dataTransfer && !this.options.dndHandler.onDragOver(new CompositeDragAndDropData('view', draggedViewId), undefined, e)) { + e.dataTransfer.dropEffect = 'none'; + } } } - } + }, + + onDragEnter: (e: DragEvent) => { + if (this.compositeTransfer.hasData(DraggedCompositeIdentifier.prototype)) { + EventHelper.stop(e, true); + + const data = this.compositeTransfer.getData(DraggedCompositeIdentifier.prototype); + if (Array.isArray(data)) { + const draggedCompositeId = data[0].id; + + // Check if drop is allowed + const validDropTarget = this.options.dndHandler.onDragEnter(new CompositeDragAndDropData('composite', draggedCompositeId), undefined, e); + this.updateFromDragging(excessDiv, validDropTarget); + } + } + + if (this.compositeTransfer.hasData(DraggedViewIdentifier.prototype)) { + EventHelper.stop(e, true); + + const data = this.compositeTransfer.getData(DraggedViewIdentifier.prototype); + if (Array.isArray(data)) { + const draggedViewId = data[0].id; + + // Check if drop is allowed + const validDropTarget = this.options.dndHandler.onDragEnter(new CompositeDragAndDropData('view', draggedViewId), undefined, e); + this.updateFromDragging(excessDiv, validDropTarget); + } + } + }, + + onDragLeave: (e: DragEvent) => { + if (this.compositeTransfer.hasData(DraggedCompositeIdentifier.prototype) || + this.compositeTransfer.hasData(DraggedViewIdentifier.prototype)) { + this.updateFromDragging(excessDiv, false); + } + }, + onDragEnd: (e: DragEvent) => { + // no-op, will not be called + }, + onDrop: (e: DragEvent) => { + if (this.compositeTransfer.hasData(DraggedCompositeIdentifier.prototype)) { + EventHelper.stop(e, true); + + const data = this.compositeTransfer.getData(DraggedCompositeIdentifier.prototype); + if (Array.isArray(data)) { + const draggedCompositeId = data[0].id; + this.compositeTransfer.clearData(DraggedCompositeIdentifier.prototype); + + this.options.dndHandler.drop(new CompositeDragAndDropData('composite', draggedCompositeId), undefined, e); + this.updateFromDragging(excessDiv, false); + } + } + + if (this.compositeTransfer.hasData(DraggedViewIdentifier.prototype)) { + const data = this.compositeTransfer.getData(DraggedViewIdentifier.prototype); + if (Array.isArray(data)) { + const draggedViewId = data[0].id; + this.compositeTransfer.clearData(DraggedViewIdentifier.prototype); + + this.options.dndHandler.drop(new CompositeDragAndDropData('view', draggedViewId), undefined, e); + this.updateFromDragging(excessDiv, false); + } + } + }, })); return actionBarDiv; @@ -432,6 +475,13 @@ export class CompositeBar extends Widget implements ICompositeBar { } } + private updateFromDragging(element: HTMLElement, isDragging: boolean): void { + const theme = this.themeService.getTheme(); + const dragBackground = this.options.colors(theme).dragAndDropBackground; + + element.style.backgroundColor = isDragging && dragBackground ? dragBackground.toString() : ''; + } + private resetActiveComposite(compositeId: string) { const defaultCompositeId = this.options.getDefaultCompositeId(); diff --git a/src/vs/workbench/browser/parts/compositeBarActions.ts b/src/vs/workbench/browser/parts/compositeBarActions.ts index 399b868395a..f4d2bf15876 100644 --- a/src/vs/workbench/browser/parts/compositeBarActions.ts +++ b/src/vs/workbench/browser/parts/compositeBarActions.ts @@ -544,7 +544,7 @@ export class CompositeActionViewItem extends ActivityActionViewItem { if (this.compositeTransfer.hasData(DraggedCompositeIdentifier.prototype)) { const data = this.compositeTransfer.getData(DraggedCompositeIdentifier.prototype); if (Array.isArray(data) && data[0].id !== this.activity.id) { - const validDropTarget = this.dndHandler.onDragOver(new CompositeDragAndDropData('composite', data[0].id), this.activity.id, e); + const validDropTarget = this.dndHandler.onDragEnter(new CompositeDragAndDropData('composite', data[0].id), this.activity.id, e); this.updateFromDragging(container, validDropTarget); } } @@ -552,7 +552,7 @@ export class CompositeActionViewItem extends ActivityActionViewItem { if (this.compositeTransfer.hasData(DraggedViewIdentifier.prototype)) { const data = this.compositeTransfer.getData(DraggedViewIdentifier.prototype); if (Array.isArray(data) && data[0].id !== this.activity.id) { - const validDropTarget = this.dndHandler.onDragOver(new CompositeDragAndDropData('view', data[0].id), this.activity.id, e); + const validDropTarget = this.dndHandler.onDragEnter(new CompositeDragAndDropData('view', data[0].id), this.activity.id, e); this.updateFromDragging(container, validDropTarget); } } diff --git a/src/vs/workbench/browser/parts/panel/media/panelpart.css b/src/vs/workbench/browser/parts/panel/media/panelpart.css index abca35a41a7..5ac0818950c 100644 --- a/src/vs/workbench/browser/parts/panel/media/panelpart.css +++ b/src/vs/workbench/browser/parts/panel/media/panelpart.css @@ -62,6 +62,10 @@ } +.monaco-workbench .part.panel > .composite.title > .composite-bar-excess { + width: 100%; +} + .monaco-workbench .part.panel > .title > .panel-switcher-container > .monaco-action-bar { line-height: 27px; /* matches panel titles in settings */ height: 35px; From 72f07ea1ae71cec5c1444e1a4b37325c6352d36c Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Thu, 27 Feb 2020 08:13:27 +0100 Subject: [PATCH 26/74] FIx #89786 --- .../workbench/contrib/extensions/browser/extensionsActions.ts | 2 +- .../extensionManagement/common/extensionManagementService.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/contrib/extensions/browser/extensionsActions.ts b/src/vs/workbench/contrib/extensions/browser/extensionsActions.ts index dec8ffa2385..e032e135584 100644 --- a/src/vs/workbench/contrib/extensions/browser/extensionsActions.ts +++ b/src/vs/workbench/contrib/extensions/browser/extensionsActions.ts @@ -2669,7 +2669,7 @@ export class SystemDisabledWarningAction extends ExtensionAction { if (server) { this.tooltip = localize('Install in other server to enable', "Install the extension on '{0}' to enable.", server.label); } else { - this.tooltip = localize('disabled because of extension kind', "This extension cannot be enabled in the remote server."); + this.tooltip = localize('disabled because of extension kind', "This extension has defined that it cannot run on the remote server"); } return; } diff --git a/src/vs/workbench/services/extensionManagement/common/extensionManagementService.ts b/src/vs/workbench/services/extensionManagement/common/extensionManagementService.ts index 4a07843244d..9f8c6ac6f5e 100644 --- a/src/vs/workbench/services/extensionManagement/common/extensionManagementService.ts +++ b/src/vs/workbench/services/extensionManagement/common/extensionManagementService.ts @@ -209,7 +209,7 @@ export class ExtensionManagementService extends Disposable implements IExtension return Promise.reject(localize('Manifest is not found', "Installing Extension {0} failed: Manifest is not found.", gallery.displayName || gallery.name)); } if (!isLanguagePackExtension(manifest) && !canExecuteOnWorkspace(manifest, this.productService, this.configurationService)) { - const error = new Error(localize('cannot be installed', "Cannot install '{0}' extension since it cannot be enabled in the remote server.", gallery.displayName || gallery.name)); + const error = new Error(localize('cannot be installed', "Cannot install '{0}' because this extension has defined that it cannot run on the remote server.", gallery.displayName || gallery.name)); error.name = INSTALL_ERROR_NOT_SUPPORTED; return Promise.reject(error); } From 93aa21cd8ae90b85a08525939ec01b8fae7d6851 Mon Sep 17 00:00:00 2001 From: SteVen Batten Date: Wed, 26 Feb 2020 23:19:19 -0800 Subject: [PATCH 27/74] fixes #91367 --- src/vs/workbench/browser/parts/views/viewPaneContainer.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/vs/workbench/browser/parts/views/viewPaneContainer.ts b/src/vs/workbench/browser/parts/views/viewPaneContainer.ts index bf954530159..21e312a5084 100644 --- a/src/vs/workbench/browser/parts/views/viewPaneContainer.ts +++ b/src/vs/workbench/browser/parts/views/viewPaneContainer.ts @@ -1009,7 +1009,8 @@ export class ViewPaneContainer extends Component implements IViewPaneContainer { } if (!this.areExtensionsReady) { if (this.visibleViewsCountFromCache === undefined) { - return true; + // TODO @sbatten fix hack for #91367 + return this.viewDescriptorService.getViewContainerLocation(this.viewContainer) === ViewContainerLocation.Panel; } // Check in cache so that view do not jump. See #29609 return this.visibleViewsCountFromCache === 1; From e9b2ec522862cc2f21e78be05352e9f9debf7e9f Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Thu, 27 Feb 2020 08:29:21 +0100 Subject: [PATCH 28/74] fixes #91062 --- src/vs/workbench/contrib/scm/browser/scmViewlet.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/scm/browser/scmViewlet.ts b/src/vs/workbench/contrib/scm/browser/scmViewlet.ts index b78b35610e7..1d3fdd35ad5 100644 --- a/src/vs/workbench/contrib/scm/browser/scmViewlet.ts +++ b/src/vs/workbench/contrib/scm/browser/scmViewlet.ts @@ -44,7 +44,7 @@ export interface ISpliceEvent { export class EmptyPane extends ViewPane { static readonly ID = 'workbench.scm'; - static readonly TITLE = localize('scm providers', "Source Control Providers"); + static readonly TITLE = localize('scm', "Source Control"); constructor( options: IViewPaneOptions, From 50ec1b1b33f81e4f6ba9313407d2f34846991187 Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Thu, 27 Feb 2020 08:31:09 +0100 Subject: [PATCH 29/74] fixes #91070 --- extensions/git/package.nls.json | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/extensions/git/package.nls.json b/extensions/git/package.nls.json index 6328edd99bf..e163ffad48d 100644 --- a/extensions/git/package.nls.json +++ b/extensions/git/package.nls.json @@ -150,11 +150,11 @@ "colors.ignored": "Color for ignored resources.", "colors.conflict": "Color for resources with conflicts.", "colors.submodule": "Color for submodule resources.", - "view.workbench.scm.missing": "A valid git installation was not detected, more details can be found in the [git output](command:git.showOutput).\nPlease [install git](https://git-scm.com/), or learn more about how to use Git and source control in VS Code in [our docs](https://aka.ms/vscode-scm).\nIf you're using a different version control system, you can [search the Marketplace](command:workbench.extensions.search?%22%40category%3A%5C%22scm%20providers%5C%22%22) for additional extensions.", - "view.workbench.scm.disabled": "If you would like to use git features, please enable git in your [settings](command:workbench.action.openSettings?%5B%22git.enabled%22%5D).\nTo learn more about how to use Git and source control in VS Code [read our docs](https://aka.ms/vscode-scm).", - "view.workbench.scm.empty": "In order to use git features, you can open a folder containing a git repository or clone from a URL.\n[Open Folder](command:vscode.openFolder)\n[Clone Repository](command:git.clone)\nTo learn more about how to use Git and source control in VS Code [read our docs](https://aka.ms/vscode-scm).", - "view.workbench.scm.folder": "The folder currently open doesn't have a git repository.\n[Initialize Repository](command:git.init?%5Btrue%5D)\nTo learn more about how to use Git and source control in VS Code [read our docs](https://aka.ms/vscode-scm).", - "view.workbench.scm.workspace": "The workspace currently open doesn't have any folders containing git repositories.\n[Initialize Repository](command:git.init)\nTo learn more about how to use Git and source control in VS Code [read our docs](https://aka.ms/vscode-scm).", - "view.workbench.scm.emptyWorkspace": "The workspace currently open doesn't have any folders containing git repositories.\n[Add Folder to Workspace](command:workbench.action.addRootFolder)\nTo learn more about how to use Git and source control in VS Code [read our docs](https://aka.ms/vscode-scm).", - "view.workbench.cloneRepository": "You can also clone a repository from a URL. To learn more about how to use Git and source control in VS Code [read our docs](https://aka.ms/vscode-scm).\n[Clone Repository](command:git.clone)" + "view.workbench.scm.missing": "A valid git installation was not detected, more details can be found in the [git output](command:git.showOutput).\nPlease [install git](https://git-scm.com/), or learn more about how to use git and source control in VS Code in [our docs](https://aka.ms/vscode-scm).\nIf you're using a different version control system, you can [search the Marketplace](command:workbench.extensions.search?%22%40category%3A%5C%22scm%20providers%5C%22%22) for additional extensions.", + "view.workbench.scm.disabled": "If you would like to use git features, please enable git in your [settings](command:workbench.action.openSettings?%5B%22git.enabled%22%5D).\nTo learn more about how to use git and source control in VS Code [read our docs](https://aka.ms/vscode-scm).", + "view.workbench.scm.empty": "In order to use git features, you can open a folder containing a git repository or clone from a URL.\n[Open Folder](command:vscode.openFolder)\n[Clone Repository](command:git.clone)\nTo learn more about how to use git and source control in VS Code [read our docs](https://aka.ms/vscode-scm).", + "view.workbench.scm.folder": "The folder currently open doesn't have a git repository.\n[Initialize Repository](command:git.init?%5Btrue%5D)\nTo learn more about how to use git and source control in VS Code [read our docs](https://aka.ms/vscode-scm).", + "view.workbench.scm.workspace": "The workspace currently open doesn't have any folders containing git repositories.\n[Initialize Repository](command:git.init)\nTo learn more about how to use git and source control in VS Code [read our docs](https://aka.ms/vscode-scm).", + "view.workbench.scm.emptyWorkspace": "The workspace currently open doesn't have any folders containing git repositories.\n[Add Folder to Workspace](command:workbench.action.addRootFolder)\nTo learn more about how to use git and source control in VS Code [read our docs](https://aka.ms/vscode-scm).", + "view.workbench.cloneRepository": "You can also clone a repository from a URL. To learn more about how to use git and source control in VS Code [read our docs](https://aka.ms/vscode-scm).\n[Clone Repository](command:git.clone)" } From 666989131e271fe7c17f620d74b37b50ec84641d Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Thu, 27 Feb 2020 08:37:26 +0100 Subject: [PATCH 30/74] fixes #91462, fixes #91465 --- .../contrib/welcome/common/viewsWelcomeExtensionPoint.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/vs/workbench/contrib/welcome/common/viewsWelcomeExtensionPoint.ts b/src/vs/workbench/contrib/welcome/common/viewsWelcomeExtensionPoint.ts index 28a5bc02dfa..8171b85762b 100644 --- a/src/vs/workbench/contrib/welcome/common/viewsWelcomeExtensionPoint.ts +++ b/src/vs/workbench/contrib/welcome/common/viewsWelcomeExtensionPoint.ts @@ -22,7 +22,7 @@ export type ViewsWelcomeExtensionPoint = ViewWelcome[]; const viewsWelcomeExtensionPointSchema = Object.freeze({ type: 'array', - description: nls.localize('contributes.viewsWelcome', "Contributed views welcome content."), + description: nls.localize('contributes.viewsWelcome', "Contributed views welcome content. Welcome content will be rendered in views whenever they have no meaningful content to display, ie. the File Explorer when no folder is open. Such content is useful as in-product documentation to drive users to use certain features before they are available. A good example would be a `Clone Repository` button in the File Explorer welcome view."), items: { type: 'object', description: nls.localize('contributes.viewsWelcome.view', "Contributed welcome content for a specific view."), @@ -33,15 +33,15 @@ const viewsWelcomeExtensionPointSchema = Object.freeze Date: Thu, 27 Feb 2020 08:56:42 +0100 Subject: [PATCH 31/74] fix global storage change events for deletes ( #91582) --- src/vs/base/parts/storage/common/storage.ts | 10 ++++--- .../parts/storage/test/node/storage.test.ts | 19 ++++++------ .../storage/browser/storageService.ts | 29 ++++++++++++++++++- src/vs/platform/storage/node/storageIpc.ts | 23 ++++++++++----- .../platform/storage/node/storageService.ts | 10 +++---- 5 files changed, 63 insertions(+), 28 deletions(-) diff --git a/src/vs/base/parts/storage/common/storage.ts b/src/vs/base/parts/storage/common/storage.ts index 03dedeca57f..2c2c909a9d1 100644 --- a/src/vs/base/parts/storage/common/storage.ts +++ b/src/vs/base/parts/storage/common/storage.ts @@ -27,7 +27,8 @@ export interface IUpdateRequest { } export interface IStorageItemsChangeEvent { - items: Map; + changed?: Map; + deleted?: Set; } export interface IStorageDatabase { @@ -104,10 +105,11 @@ export class Storage extends Disposable implements IStorage { // items that change external require us to update our // caches with the values. we just accept the value and // emit an event if there is a change. - e.items.forEach((value, key) => this.accept(key, value)); + e.changed?.forEach((value, key) => this.accept(key, value)); + e.deleted?.forEach(key => this.accept(key, undefined)); } - private accept(key: string, value: string): void { + private accept(key: string, value: string | undefined): void { if (this.state === StorageState.Closed) { return; // Return early if we are already closed } @@ -315,4 +317,4 @@ export class InMemoryStorageDatabase implements IStorageDatabase { close(): Promise { return Promise.resolve(); } -} \ No newline at end of file +} diff --git a/src/vs/base/parts/storage/test/node/storage.test.ts b/src/vs/base/parts/storage/test/node/storage.test.ts index 9c966c0868b..5c25b92dffc 100644 --- a/src/vs/base/parts/storage/test/node/storage.test.ts +++ b/src/vs/base/parts/storage/test/node/storage.test.ts @@ -124,28 +124,27 @@ suite('Storage Library', () => { changes.clear(); // Nothing happens if changing to same value - const change = new Map(); - change.set('foo', 'bar'); - database.fireDidChangeItemsExternal({ items: change }); + const changed = new Map(); + changed.set('foo', 'bar'); + database.fireDidChangeItemsExternal({ changed }); equal(changes.size, 0); // Change is accepted if valid - change.set('foo', 'bar1'); - database.fireDidChangeItemsExternal({ items: change }); + changed.set('foo', 'bar1'); + database.fireDidChangeItemsExternal({ changed }); ok(changes.has('foo')); equal(storage.get('foo'), 'bar1'); changes.clear(); // Delete is accepted - change.set('foo', undefined!); - database.fireDidChangeItemsExternal({ items: change }); + const deleted = new Set(['foo']); + database.fireDidChangeItemsExternal({ deleted }); ok(changes.has('foo')); - equal(storage.get('foo', null!), null); + equal(storage.get('foo', undefined), undefined); changes.clear(); // Nothing happens if changing to same value - change.set('foo', undefined!); - database.fireDidChangeItemsExternal({ items: change }); + database.fireDidChangeItemsExternal({ deleted }); equal(changes.size, 0); await storage.close(); diff --git a/src/vs/platform/storage/browser/storageService.ts b/src/vs/platform/storage/browser/storageService.ts index 839f2c94ff9..1c8174147b0 100644 --- a/src/vs/platform/storage/browser/storageService.ts +++ b/src/vs/platform/storage/browser/storageService.ts @@ -240,9 +240,36 @@ export class FileStorageDatabase extends Disposable implements IStorageDatabase private async onDidStorageChangeExternal(): Promise { const items = await this.doGetItemsFromFile(); + // pervious cache, diff for changes + let changed = new Map(); + let deleted = new Set(); + if (this.cache) { + items.forEach((value, key) => { + const existingValue = this.cache?.get(key); + if (existingValue !== value) { + changed.set(key, value); + } + }); + + this.cache.forEach((_, key) => { + if (!items.has(key)) { + deleted.add(key); + } + }); + } + + // no previous cache, consider all as changed + else { + changed = items; + } + + // Update cache this.cache = items; - this._onDidChangeItemsExternal.fire({ items }); + // Emit as event as needed + if (changed.size > 0 || deleted.size > 0) { + this._onDidChangeItemsExternal.fire({ changed, deleted }); + } } async getItems(): Promise> { diff --git a/src/vs/platform/storage/node/storageIpc.ts b/src/vs/platform/storage/node/storageIpc.ts index e2bbca21641..a6f2367f355 100644 --- a/src/vs/platform/storage/node/storageIpc.ts +++ b/src/vs/platform/storage/node/storageIpc.ts @@ -24,15 +24,16 @@ interface ISerializableUpdateRequest { } interface ISerializableItemsChangeEvent { - items: Item[]; + changed?: Item[]; + deleted?: Key[]; } export class GlobalStorageDatabaseChannel extends Disposable implements IServerChannel { private static readonly STORAGE_CHANGE_DEBOUNCE_TIME = 100; - private readonly _onDidChangeItems: Emitter = this._register(new Emitter()); - readonly onDidChangeItems: Event = this._onDidChangeItems.event; + private readonly _onDidChangeItems = this._register(new Emitter()); + readonly onDidChangeItems = this._onDidChangeItems.event; private whenReady: Promise; @@ -99,15 +100,18 @@ export class GlobalStorageDatabaseChannel extends Disposable implements IServerC } private serializeEvents(events: IStorageChangeEvent[]): ISerializableItemsChangeEvent { - const items = new Map(); + const changed = new Map(); + const deleted = new Set(); events.forEach(event => { const existing = this.storageMainService.get(event.key); if (typeof existing === 'string') { - items.set(event.key, existing); + changed.set(event.key, existing); + } else { + deleted.add(event.key); } }); - return { items: mapToSerializable(items) }; + return { changed: mapToSerializable(changed), deleted: values(deleted) }; } listen(_: unknown, event: string): Event { @@ -170,8 +174,11 @@ export class GlobalStorageDatabaseChannelClient extends Disposable implements IS } private onDidChangeItemsOnMain(e: ISerializableItemsChangeEvent): void { - if (Array.isArray(e.items)) { - this._onDidChangeItemsExternal.fire({ items: serializableToMap(e.items) }); + if (Array.isArray(e.changed) || Array.isArray(e.deleted)) { + this._onDidChangeItemsExternal.fire({ + changed: e.changed ? serializableToMap(e.changed) : undefined, + deleted: e.deleted ? new Set(e.deleted) : undefined + }); } } diff --git a/src/vs/platform/storage/node/storageService.ts b/src/vs/platform/storage/node/storageService.ts index 1aed6216d8f..cf68e7b5aac 100644 --- a/src/vs/platform/storage/node/storageService.ts +++ b/src/vs/platform/storage/node/storageService.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { Disposable, IDisposable, dispose } from 'vs/base/common/lifecycle'; -import { Event, Emitter } from 'vs/base/common/event'; +import { Emitter } from 'vs/base/common/event'; import { ILogService, LogLevel } from 'vs/platform/log/common/log'; import { IWorkspaceStorageChangeEvent, IStorageService, StorageScope, IWillSaveStateEvent, WillSaveStateReason, logStorage } from 'vs/platform/storage/common/storage'; import { SQLiteStorageDatabase, ISQLiteStorageDatabaseLoggingOptions } from 'vs/base/parts/storage/node/storage'; @@ -25,11 +25,11 @@ export class NativeStorageService extends Disposable implements IStorageService private static readonly WORKSPACE_STORAGE_NAME = 'state.vscdb'; private static readonly WORKSPACE_META_NAME = 'workspace.json'; - private readonly _onDidChangeStorage: Emitter = this._register(new Emitter()); - readonly onDidChangeStorage: Event = this._onDidChangeStorage.event; + private readonly _onDidChangeStorage = this._register(new Emitter()); + readonly onDidChangeStorage = this._onDidChangeStorage.event; - private readonly _onWillSaveState: Emitter = this._register(new Emitter()); - readonly onWillSaveState: Event = this._onWillSaveState.event; + private readonly _onWillSaveState = this._register(new Emitter()); + readonly onWillSaveState = this._onWillSaveState.event; private globalStorage: IStorage; From 3cc41d42718c3a124aa5900604a3336cd6f471fb Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Thu, 27 Feb 2020 09:05:51 +0100 Subject: [PATCH 32/74] update docs for #91242 --- src/vs/vscode.d.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/vscode.d.ts b/src/vs/vscode.d.ts index 52c6a90f94e..207183cb8d8 100644 --- a/src/vs/vscode.d.ts +++ b/src/vs/vscode.d.ts @@ -1500,7 +1500,7 @@ declare module 'vscode' { /** * A file system watcher notifies about changes to files and folders - * on disk. + * on disk or from other [FileSystemProviders](#FileSystemProvider). * * To get an instance of a `FileSystemWatcher` use * [createFileSystemWatcher](#workspace.createFileSystemWatcher). From d5661c98ddee18be82ad2fdfbacf640590ece30a Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Thu, 27 Feb 2020 09:06:18 +0100 Subject: [PATCH 33/74] fixes #91471 --- src/vs/workbench/common/views.ts | 18 ++++++++++++++++-- .../welcome/common/viewsWelcomeContribution.ts | 5 +++-- 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/src/vs/workbench/common/views.ts b/src/vs/workbench/common/views.ts index d1b30384874..6b29b27222e 100644 --- a/src/vs/workbench/common/views.ts +++ b/src/vs/workbench/common/views.ts @@ -17,7 +17,7 @@ import { Registry } from 'vs/platform/registry/common/platform'; import { IKeybindings } from 'vs/platform/keybinding/common/keybindingsRegistry'; import { IAction, IActionViewItem } from 'vs/base/common/actions'; import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions'; -import { flatten } from 'vs/base/common/arrays'; +import { flatten, mergeSort } from 'vs/base/common/arrays'; import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors'; import { SetMap } from 'vs/base/common/collections'; @@ -212,9 +212,16 @@ export interface IViewDescriptorCollection extends IDisposable { readonly allViewDescriptors: IViewDescriptor[]; } +export enum ViewContentPriority { + Normal = 0, + Low = 1, + Lowest = 2 +} + export interface IViewContentDescriptor { readonly content: string; readonly when?: ContextKeyExpr | 'default'; + readonly priority?: ViewContentPriority; /** * ordered preconditions for each button in the content @@ -248,6 +255,13 @@ export interface IViewsRegistry { } function compareViewContentDescriptors(a: IViewContentDescriptor, b: IViewContentDescriptor): number { + const aPriority = a.priority ?? ViewContentPriority.Normal; + const bPriority = b.priority ?? ViewContentPriority.Normal; + + if (aPriority !== bPriority) { + return aPriority - bPriority; + } + return a.content < b.content ? -1 : 1; } @@ -329,8 +343,8 @@ class ViewsRegistry extends Disposable implements IViewsRegistry { getViewWelcomeContent(id: string): IViewContentDescriptor[] { const result: IViewContentDescriptor[] = []; - result.sort(compareViewContentDescriptors); this._viewWelcomeContents.forEach(id, descriptor => result.push(descriptor)); + mergeSort(result, compareViewContentDescriptors); return result; } diff --git a/src/vs/workbench/contrib/welcome/common/viewsWelcomeContribution.ts b/src/vs/workbench/contrib/welcome/common/viewsWelcomeContribution.ts index 51fb3194e95..8506ff7eb34 100644 --- a/src/vs/workbench/contrib/welcome/common/viewsWelcomeContribution.ts +++ b/src/vs/workbench/contrib/welcome/common/viewsWelcomeContribution.ts @@ -9,7 +9,7 @@ import { IWorkbenchContribution } from 'vs/workbench/common/contributions'; import { IExtensionPoint } from 'vs/workbench/services/extensions/common/extensionsRegistry'; import { ViewsWelcomeExtensionPoint, ViewWelcome, viewsWelcomeExtensionPointDescriptor } from './viewsWelcomeExtensionPoint'; import { Registry } from 'vs/platform/registry/common/platform'; -import { Extensions as ViewContainerExtensions, IViewsRegistry } from 'vs/workbench/common/views'; +import { Extensions as ViewContainerExtensions, IViewsRegistry, ViewContentPriority } from 'vs/workbench/common/views'; import { localize } from 'vs/nls'; const viewsRegistry = Registry.as(ViewContainerExtensions.ViewsRegistry); @@ -47,7 +47,8 @@ export class ViewsWelcomeContribution extends Disposable implements IWorkbenchCo for (const welcome of contribution.value) { const disposable = viewsRegistry.registerViewWelcomeContent(welcome.view, { content: welcome.contents, - when: ContextKeyExpr.deserialize(welcome.when) + when: ContextKeyExpr.deserialize(welcome.when), + priority: contribution.description.isBuiltin ? ViewContentPriority.Low : ViewContentPriority.Lowest }); this.viewWelcomeContents.set(welcome, disposable); From 52901c545b4a098748d5f08c2e994c309738453c Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Thu, 27 Feb 2020 09:07:33 +0100 Subject: [PATCH 34/74] Two icons for representing notification progress are confusing (fix #91469) --- .../browser/parts/notifications/notificationsStatus.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/vs/workbench/browser/parts/notifications/notificationsStatus.ts b/src/vs/workbench/browser/parts/notifications/notificationsStatus.ts index 1bdde771ccb..cf45117e80c 100644 --- a/src/vs/workbench/browser/parts/notifications/notificationsStatus.ts +++ b/src/vs/workbench/browser/parts/notifications/notificationsStatus.ts @@ -69,8 +69,9 @@ export class NotificationsStatus extends Disposable { } } + // Show the bell with a dot if there are unread or in-progress notifications const statusProperties: IStatusbarEntry = { - text: `${this.newNotificationsCount === 0 ? '$(bell)' : '$(bell-dot)'}${notificationsInProgress > 0 ? ' $(sync~spin)' : ''}`, + text: `${notificationsInProgress > 0 || this.newNotificationsCount > 0 ? '$(bell-dot)' : '$(bell)'}`, command: this.isNotificationsCenterVisible ? HIDE_NOTIFICATIONS_CENTER : SHOW_NOTIFICATIONS_CENTER, tooltip: this.getTooltip(notificationsInProgress), showBeak: this.isNotificationsCenterVisible From 04c9b01affe9201c3c96533aba56639e810e940f Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Thu, 27 Feb 2020 09:24:38 +0100 Subject: [PATCH 35/74] fixes #91466 --- extensions/git/package.json | 14 +++++++------- .../welcome/common/viewsWelcomeContribution.ts | 5 +++-- .../welcome/common/viewsWelcomeExtensionPoint.ts | 7 +++++++ 3 files changed, 17 insertions(+), 9 deletions(-) diff --git a/extensions/git/package.json b/extensions/git/package.json index 1eaf39ad44b..5246020c6c2 100644 --- a/extensions/git/package.json +++ b/extensions/git/package.json @@ -1825,37 +1825,37 @@ }, "viewsWelcome": [ { - "view": "workbench.scm", + "view": "scm", "contents": "%view.workbench.scm.disabled%", "when": "!config.git.enabled" }, { - "view": "workbench.scm", + "view": "scm", "contents": "%view.workbench.scm.missing%", "when": "config.git.enabled && git.missing" }, { - "view": "workbench.scm", + "view": "scm", "contents": "%view.workbench.scm.empty%", "when": "config.git.enabled && !git.missing && workbenchState == empty" }, { - "view": "workbench.scm", + "view": "scm", "contents": "%view.workbench.scm.folder%", "when": "config.git.enabled && !git.missing && workbenchState == folder" }, { - "view": "workbench.scm", + "view": "scm", "contents": "%view.workbench.scm.workspace%", "when": "config.git.enabled && !git.missing && workbenchState == workspace && workspaceFolderCount != 0" }, { - "view": "workbench.scm", + "view": "scm", "contents": "%view.workbench.scm.emptyWorkspace%", "when": "config.git.enabled && !git.missing && workbenchState == workspace && workspaceFolderCount == 0" }, { - "view": "workbench.explorer.emptyView", + "view": "explorer", "contents": "%view.workbench.cloneRepository%" } ] diff --git a/src/vs/workbench/contrib/welcome/common/viewsWelcomeContribution.ts b/src/vs/workbench/contrib/welcome/common/viewsWelcomeContribution.ts index 8506ff7eb34..e7e50346aa5 100644 --- a/src/vs/workbench/contrib/welcome/common/viewsWelcomeContribution.ts +++ b/src/vs/workbench/contrib/welcome/common/viewsWelcomeContribution.ts @@ -7,7 +7,7 @@ import { Disposable, IDisposable } from 'vs/base/common/lifecycle'; import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey'; import { IWorkbenchContribution } from 'vs/workbench/common/contributions'; import { IExtensionPoint } from 'vs/workbench/services/extensions/common/extensionsRegistry'; -import { ViewsWelcomeExtensionPoint, ViewWelcome, viewsWelcomeExtensionPointDescriptor } from './viewsWelcomeExtensionPoint'; +import { ViewsWelcomeExtensionPoint, ViewWelcome, viewsWelcomeExtensionPointDescriptor, ViewIdentifierMap } from './viewsWelcomeExtensionPoint'; import { Registry } from 'vs/platform/registry/common/platform'; import { Extensions as ViewContainerExtensions, IViewsRegistry, ViewContentPriority } from 'vs/workbench/common/views'; import { localize } from 'vs/nls'; @@ -45,7 +45,8 @@ export class ViewsWelcomeContribution extends Disposable implements IWorkbenchCo } for (const welcome of contribution.value) { - const disposable = viewsRegistry.registerViewWelcomeContent(welcome.view, { + const id = ViewIdentifierMap[welcome.view] ?? welcome.view; + const disposable = viewsRegistry.registerViewWelcomeContent(id, { content: welcome.contents, when: ContextKeyExpr.deserialize(welcome.when), priority: contribution.description.isBuiltin ? ViewContentPriority.Low : ViewContentPriority.Lowest diff --git a/src/vs/workbench/contrib/welcome/common/viewsWelcomeExtensionPoint.ts b/src/vs/workbench/contrib/welcome/common/viewsWelcomeExtensionPoint.ts index 8171b85762b..9a1fdbe078e 100644 --- a/src/vs/workbench/contrib/welcome/common/viewsWelcomeExtensionPoint.ts +++ b/src/vs/workbench/contrib/welcome/common/viewsWelcomeExtensionPoint.ts @@ -20,6 +20,12 @@ export interface ViewWelcome { export type ViewsWelcomeExtensionPoint = ViewWelcome[]; +export const ViewIdentifierMap: { [key: string]: string } = { + 'explorer': 'workbench.explorer.emptyView', + 'debug': 'workbench.debug.startView', + 'scm': 'workbench.scm', +}; + const viewsWelcomeExtensionPointSchema = Object.freeze({ type: 'array', description: nls.localize('contributes.viewsWelcome', "Contributed views welcome content. Welcome content will be rendered in views whenever they have no meaningful content to display, ie. the File Explorer when no folder is open. Such content is useful as in-product documentation to drive users to use certain features before they are available. A good example would be a `Clone Repository` button in the File Explorer welcome view."), @@ -34,6 +40,7 @@ const viewsWelcomeExtensionPointSchema = Object.freeze Date: Thu, 27 Feb 2020 09:35:12 +0100 Subject: [PATCH 36/74] dispose quick pick --- .../workbench/contrib/userDataSync/browser/userDataSync.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/contrib/userDataSync/browser/userDataSync.ts b/src/vs/workbench/contrib/userDataSync/browser/userDataSync.ts index 3769fabc22a..aeb8ef22ab9 100644 --- a/src/vs/workbench/contrib/userDataSync/browser/userDataSync.ts +++ b/src/vs/workbench/contrib/userDataSync/browser/userDataSync.ts @@ -552,8 +552,8 @@ export class UserDataSyncWorkbenchContribution extends Disposable implements IWo const disposables: DisposableStore = new DisposableStore(); const displayName = this.authenticationService.getDisplayName(this.userDataSyncStore!.authenticationProviderId); const quickPick = this.quickInputService.createQuickPick<{ id: string, label: string, description?: string, detail?: string }>(); - const chooseAnotherItemId = 'chooseAnother'; disposables.add(quickPick); + const chooseAnotherItemId = 'chooseAnother'; quickPick.title = localize('pick account', "{0}: Pick an account", displayName); quickPick.ok = false; quickPick.placeholder = localize('choose account placeholder', "Pick an account for syncing"); @@ -916,7 +916,9 @@ export class UserDataSyncWorkbenchContribution extends Disposable implements IWo return new Promise((c, e) => { const quickInputService = accessor.get(IQuickInputService); const commandService = accessor.get(ICommandService); + const disposables = new DisposableStore(); const quickPick = quickInputService.createQuickPick(); + disposables.add(quickPick); const items: Array = []; if (that.userDataSyncService.conflictsSources.length) { for (const source of that.userDataSyncService.conflictsSources) { @@ -937,7 +939,6 @@ export class UserDataSyncWorkbenchContribution extends Disposable implements IWo items.push({ type: 'separator' }); items.push({ id: stopSyncCommand.id, label: stopSyncCommand.title(that.userDataSyncStore!.authenticationProviderId, that.activeAccount, that.authenticationService) }); quickPick.items = items; - const disposables = new DisposableStore(); disposables.add(quickPick.onDidAccept(() => { if (quickPick.selectedItems[0] && quickPick.selectedItems[0].id) { commandService.executeCommand(quickPick.selectedItems[0].id); From 9ee247f352d7fe1ba3a9bc6217c5661694bd49d9 Mon Sep 17 00:00:00 2001 From: Gustavo Cassel Date: Thu, 27 Feb 2020 05:47:16 -0300 Subject: [PATCH 37/74] Improved documentation of 'title' property on OpenDialogOptions and SaveDialogOptions (#91633) --- src/vs/vscode.proposed.d.ts | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/vs/vscode.proposed.d.ts b/src/vs/vscode.proposed.d.ts index b3bea7c0a5a..6c28f957862 100644 --- a/src/vs/vscode.proposed.d.ts +++ b/src/vs/vscode.proposed.d.ts @@ -1705,7 +1705,10 @@ declare module 'vscode' { */ export interface OpenDialogOptions { /** - * Dialog title + * Dialog title. + * + * Depending on the underlying operating system this parameter might be ignored, since some + * systems do not present title on open dialogs. */ title?: string; } @@ -1715,7 +1718,10 @@ declare module 'vscode' { */ export interface SaveDialogOptions { /** - * Dialog title + * Dialog title. + * + * Depending on the underlying operating system this parameter might be ignored, since some + * systems do not present title on save dialogs. */ title?: string; } From 4fa435b69b32b7f7ee4740f1787497edb54ef1de Mon Sep 17 00:00:00 2001 From: Christof Marti Date: Thu, 27 Feb 2020 09:47:28 +0100 Subject: [PATCH 38/74] Show OK by default for multi-select (fixes #90365) --- src/vs/base/parts/quickinput/browser/quickInput.ts | 7 ++++--- src/vs/base/parts/quickinput/common/quickInput.ts | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/vs/base/parts/quickinput/browser/quickInput.ts b/src/vs/base/parts/quickinput/browser/quickInput.ts index 059eb29406d..d3d94acb6ad 100644 --- a/src/vs/base/parts/quickinput/browser/quickInput.ts +++ b/src/vs/base/parts/quickinput/browser/quickInput.ts @@ -397,7 +397,7 @@ class QuickPick extends QuickInput implements IQuickPi private _valueSelection: Readonly<[number, number]> | undefined; private valueSelectionUpdated = true; private _validationMessage: string | undefined; - private _ok = false; + private _ok: boolean | 'default' = 'default'; private _customButton = false; private _customButtonLabel: string | undefined; private _customButtonHover: string | undefined; @@ -566,7 +566,7 @@ class QuickPick extends QuickInput implements IQuickPi return this._ok; } - set ok(showOkButton: boolean) { + set ok(showOkButton: boolean | 'default') { this._ok = showOkButton; this.update(); } @@ -757,7 +757,8 @@ class QuickPick extends QuickInput implements IQuickPi if (!this.visible) { return; } - this.ui.setVisibilities(this.canSelectMany ? { title: !!this.title || !!this.step, description: !!this.description, checkAll: true, inputBox: true, visibleCount: true, count: true, ok: this.ok, list: true, message: !!this.validationMessage, customButton: this.customButton } : { title: !!this.title || !!this.step, description: !!this.description, inputBox: true, visibleCount: true, list: true, message: !!this.validationMessage, customButton: this.customButton, ok: this.ok }); + const ok = this.ok === 'default' ? this.canSelectMany : this.ok; + this.ui.setVisibilities(this.canSelectMany ? { title: !!this.title || !!this.step, description: !!this.description, checkAll: true, inputBox: true, visibleCount: true, count: true, ok, list: true, message: !!this.validationMessage, customButton: this.customButton } : { title: !!this.title || !!this.step, description: !!this.description, inputBox: true, visibleCount: true, list: true, message: !!this.validationMessage, customButton: this.customButton, ok }); super.update(); if (this.ui.inputBox.value !== this.value) { this.ui.inputBox.value = this.value; diff --git a/src/vs/base/parts/quickinput/common/quickInput.ts b/src/vs/base/parts/quickinput/common/quickInput.ts index 36905c59c53..10c8255a444 100644 --- a/src/vs/base/parts/quickinput/common/quickInput.ts +++ b/src/vs/base/parts/quickinput/common/quickInput.ts @@ -162,7 +162,7 @@ export interface IQuickPick extends IQuickInput { readonly onDidAccept: Event; - ok: boolean; + ok: boolean | 'default'; readonly onDidCustom: Event; From 96dfec43ee7ecc124ca6d9d4a4e41aac5ea56ab3 Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Thu, 27 Feb 2020 09:58:01 +0100 Subject: [PATCH 39/74] fixes #90934 --- extensions/git/src/commands.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/extensions/git/src/commands.ts b/extensions/git/src/commands.ts index ad4d47485e7..10d2cfc2d5b 100644 --- a/extensions/git/src/commands.ts +++ b/extensions/git/src/commands.ts @@ -1397,12 +1397,16 @@ export class CommandCenter { opts.signoff = true; } + const smartCommitChanges = config.get<'all' | 'tracked'>('smartCommitChanges'); + if ( ( // no changes (noStagedChanges && noUnstagedChanges) // or no staged changes and not `all` || (!opts.all && noStagedChanges) + // no staged changes and no tracked unstaged changes + || (noStagedChanges && smartCommitChanges === 'tracked' && repository.workingTreeGroup.resourceStates.every(r => r.type === Status.UNTRACKED)) ) && !opts.empty ) { @@ -1416,7 +1420,7 @@ export class CommandCenter { return false; } - if (opts.all && config.get<'all' | 'tracked'>('smartCommitChanges') === 'tracked') { + if (opts.all && smartCommitChanges === 'tracked') { opts.all = 'tracked'; } From 1c0ac37b1e189eecaa9c380a442534cb79c053be Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Thu, 27 Feb 2020 10:41:36 +0100 Subject: [PATCH 40/74] fix #91665 --- .../editor/contrib/gotoSymbol/link/goToDefinitionAtPosition.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/vs/editor/contrib/gotoSymbol/link/goToDefinitionAtPosition.ts b/src/vs/editor/contrib/gotoSymbol/link/goToDefinitionAtPosition.ts index a2ac8275f37..68c3275a7a4 100644 --- a/src/vs/editor/contrib/gotoSymbol/link/goToDefinitionAtPosition.ts +++ b/src/vs/editor/contrib/gotoSymbol/link/goToDefinitionAtPosition.ts @@ -338,9 +338,8 @@ export class GotoDefinitionAtPositionEditorContribution implements IEditorContri private gotoDefinition(position: Position, openToSide: boolean): Promise { this.editor.setPosition(position); - const definitionLinkOpensInPeek = this.editor.getOption(EditorOption.definitionLinkOpensInPeek); return this.editor.invokeWithinContext((accessor) => { - const canPeek = definitionLinkOpensInPeek && !this.isInPeekEditor(accessor); + const canPeek = !openToSide && this.editor.getOption(EditorOption.definitionLinkOpensInPeek) && !this.isInPeekEditor(accessor); const action = new DefinitionAction({ openToSide, openInPeek: canPeek, muteMessage: true }, { alias: '', label: '', id: '', precondition: undefined }); return action.run(accessor, this.editor); }); From 05549445001dad9c611237d2e7f8b927fa76037a Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Thu, 27 Feb 2020 10:57:00 +0100 Subject: [PATCH 41/74] refine wording for settings doc, #62571 --- src/vs/editor/common/config/editorOptions.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/editor/common/config/editorOptions.ts b/src/vs/editor/common/config/editorOptions.ts index 270e0018dff..f2873a887f8 100644 --- a/src/vs/editor/common/config/editorOptions.ts +++ b/src/vs/editor/common/config/editorOptions.ts @@ -3769,7 +3769,7 @@ export const EditorOptions = { )), definitionLinkOpensInPeek: register(new EditorBooleanOption( EditorOption.definitionLinkOpensInPeek, 'definitionLinkOpensInPeek', false, - { description: nls.localize('definitionLinkOpensInPeek', "Controls whether the definition link opens element in the peek widget.") } + { description: nls.localize('definitionLinkOpensInPeek', "Controls whether the Go to Definition mouse gesture always opens the peek widget.") } )), quickSuggestions: register(new EditorQuickSuggestions()), quickSuggestionsDelay: register(new EditorIntOption( From 9ff4a28982b2ced53660c77e0b281133328ac1ec Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Thu, 27 Feb 2020 11:04:14 +0100 Subject: [PATCH 42/74] text files - trace dispose() calls --- .../workbench/services/textfile/common/textFileEditorModel.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/vs/workbench/services/textfile/common/textFileEditorModel.ts b/src/vs/workbench/services/textfile/common/textFileEditorModel.ts index 67332750e50..949e69d12ef 100644 --- a/src/vs/workbench/services/textfile/common/textFileEditorModel.ts +++ b/src/vs/workbench/services/textfile/common/textFileEditorModel.ts @@ -919,6 +919,8 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil } dispose(): void { + this.logService.trace('[text file model] dispose()', this.resource.toString(true)); + this.disposed = true; this.inConflictMode = false; this.inOrphanMode = false; From 864f21ad6144b72cbb21b8752ae226d8d06f940f Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Thu, 27 Feb 2020 11:19:59 +0100 Subject: [PATCH 43/74] tests - exit CLI process when renderer crashes or is unresponsive instead of bringing up a dialog --- src/vs/code/electron-main/window.ts | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/vs/code/electron-main/window.ts b/src/vs/code/electron-main/window.ts index 1f1c08a58f1..55600018311 100644 --- a/src/vs/code/electron-main/window.ts +++ b/src/vs/code/electron-main/window.ts @@ -32,6 +32,7 @@ import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { IDialogMainService } from 'vs/platform/dialogs/electron-main/dialogs'; import { mnemonicButtonLabel } from 'vs/base/common/labels'; import { ThemeIcon } from 'vs/platform/theme/common/themeService'; +import { ILifecycleMainService } from 'vs/platform/lifecycle/electron-main/lifecycleMainService'; const RUN_TEXTMATE_IN_WORKER = false; @@ -100,7 +101,8 @@ export class CodeWindow extends Disposable implements ICodeWindow { @IWorkspacesMainService private readonly workspacesMainService: IWorkspacesMainService, @IBackupMainService private readonly backupMainService: IBackupMainService, @ITelemetryService private readonly telemetryService: ITelemetryService, - @IDialogMainService private readonly dialogMainService: IDialogMainService + @IDialogMainService private readonly dialogMainService: IDialogMainService, + @ILifecycleMainService private readonly lifecycleMainService: ILifecycleMainService ) { super(); @@ -244,6 +246,8 @@ export class CodeWindow extends Disposable implements ICodeWindow { get isExtensionTestHost(): boolean { return !!(this.config && this.config.extensionTestsPath); } + get isExtensionDevelopmentTestFromCli(): boolean { return this.isExtensionDevelopmentHost && this.isExtensionTestHost && !this.config?.debugId; } + setRepresentedFilename(filename: string): void { if (isMacintosh) { this.win.setRepresentedFilename(filename); @@ -447,6 +451,15 @@ export class CodeWindow extends Disposable implements ICodeWindow { private onWindowError(error: WindowError): void { this.logService.error(error === WindowError.CRASHED ? '[VS Code]: render process crashed!' : '[VS Code]: detected unresponsive'); + // If we run extension tests from CLI, showing a dialog is not + // very helpful in this case. Rather, we bring down the test run + // to signal back a failing run. + if (this.isExtensionDevelopmentTestFromCli) { + this.lifecycleMainService.kill(1); + return; + } + + // Telemetry type WindowErrorClassification = { type: { classification: 'SystemMetaData', purpose: 'PerformanceAndHealth', isMeasurement: true }; }; From 24307c0e1b012c493a1763024371a2f805c97da9 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Thu, 27 Feb 2020 11:25:58 +0100 Subject: [PATCH 44/74] Support Link Titles with single quotes in Welcome Views (fix #91442) --- src/vs/base/common/linkedText.ts | 2 +- src/vs/base/test/common/linkedText.test.ts | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/vs/base/common/linkedText.ts b/src/vs/base/common/linkedText.ts index ee268d9fdcd..65e48078110 100644 --- a/src/vs/base/common/linkedText.ts +++ b/src/vs/base/common/linkedText.ts @@ -23,7 +23,7 @@ export class LinkedText { } } -const LINK_REGEX = /\[([^\]]+)\]\(((?:https?:\/\/|command:)[^\)\s]+)(?: "([^"]+)")?\)/gi; +const LINK_REGEX = /\[([^\]]+)\]\(((?:https?:\/\/|command:)[^\)\s]+)(?: (?:"|')([^"]+)(?:"|'))?\)/gi; export function parseLinkedText(text: string): LinkedText { const result: LinkedTextNode[] = []; diff --git a/src/vs/base/test/common/linkedText.test.ts b/src/vs/base/test/common/linkedText.test.ts index 8e1cb887485..15185ef44ae 100644 --- a/src/vs/base/test/common/linkedText.test.ts +++ b/src/vs/base/test/common/linkedText.test.ts @@ -21,6 +21,11 @@ suite('LinkedText', () => { { label: 'link text', href: 'http://link.href', title: 'and a title' }, '.' ]); + assert.deepEqual(parseLinkedText('Some message with [link text](http://link.href \'and a title\').').nodes, [ + 'Some message with ', + { label: 'link text', href: 'http://link.href', title: 'and a title' }, + '.' + ]); assert.deepEqual(parseLinkedText('Some message with [link text](random stuff).').nodes, [ 'Some message with [link text](random stuff).' ]); From 15bdd26e460fb16ca3cca2202875de4d31863f4c Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Thu, 27 Feb 2020 11:41:09 +0100 Subject: [PATCH 45/74] fix #91672 --- .../contrib/bulkEdit/browser/bulkEdit.contribution.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/contrib/bulkEdit/browser/bulkEdit.contribution.ts b/src/vs/workbench/contrib/bulkEdit/browser/bulkEdit.contribution.ts index 66624cf7bb6..faf9b538534 100644 --- a/src/vs/workbench/contrib/bulkEdit/browser/bulkEdit.contribution.ts +++ b/src/vs/workbench/contrib/bulkEdit/browser/bulkEdit.contribution.ts @@ -111,6 +111,7 @@ class BulkEditPreviewContribution { private async _previewEdit(edit: WorkspaceEdit) { this._ctxEnabled.set(true); + const uxState = this._activeSession?.uxState ?? new UXState(this._panelService, this._editorGroupsService); const view = await getBulkEditPane(this._viewsService); if (!view) { this._ctxEnabled.set(false); @@ -136,9 +137,9 @@ class BulkEditPreviewContribution { let session: PreviewSession; if (this._activeSession) { this._activeSession.cts.dispose(true); - session = new PreviewSession(this._activeSession.uxState); + session = new PreviewSession(uxState); } else { - session = new PreviewSession(new UXState(this._panelService, this._editorGroupsService)); + session = new PreviewSession(uxState); } this._activeSession = session; From 8758dc9dddf95f358eb93c969353e5cf245ed1e4 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Thu, 27 Feb 2020 11:50:18 +0100 Subject: [PATCH 46/74] Fixes #91405: Improve minimap settings --- .../browser/viewParts/minimap/minimap.ts | 6 ++--- src/vs/editor/common/config/editorOptions.ts | 26 +++++++++---------- .../viewLayout/editorLayoutProvider.test.ts | 12 ++++----- src/vs/monaco.d.ts | 2 +- 4 files changed, 23 insertions(+), 23 deletions(-) diff --git a/src/vs/editor/browser/viewParts/minimap/minimap.ts b/src/vs/editor/browser/viewParts/minimap/minimap.ts index d5aa95d0611..4e2808594db 100644 --- a/src/vs/editor/browser/viewParts/minimap/minimap.ts +++ b/src/vs/editor/browser/viewParts/minimap/minimap.ts @@ -46,7 +46,7 @@ class MinimapOptions { public readonly renderMinimap: RenderMinimap; - public readonly mode: 'actual' | 'cover' | 'contain'; + public readonly size: 'proportional' | 'fill' | 'fit'; public readonly minimapHeightIsEditorHeight: boolean; @@ -108,7 +108,7 @@ class MinimapOptions { const minimapOpts = options.get(EditorOption.minimap); this.renderMinimap = layoutInfo.renderMinimap | 0; - this.mode = minimapOpts.mode; + this.size = minimapOpts.size; this.minimapHeightIsEditorHeight = layoutInfo.minimapHeightIsEditorHeight; this.scrollBeyondLastLine = options.get(EditorOption.scrollBeyondLastLine); this.showSlider = minimapOpts.showSlider; @@ -144,7 +144,7 @@ class MinimapOptions { public equals(other: MinimapOptions): boolean { return (this.renderMinimap === other.renderMinimap - && this.mode === other.mode + && this.size === other.size && this.minimapHeightIsEditorHeight === other.minimapHeightIsEditorHeight && this.scrollBeyondLastLine === other.scrollBeyondLastLine && this.showSlider === other.showSlider diff --git a/src/vs/editor/common/config/editorOptions.ts b/src/vs/editor/common/config/editorOptions.ts index f2873a887f8..e149ea0793c 100644 --- a/src/vs/editor/common/config/editorOptions.ts +++ b/src/vs/editor/common/config/editorOptions.ts @@ -1802,7 +1802,7 @@ export class EditorLayoutInfoComputer extends ComputedEditorOption= 2 ? Math.round(minimap.scale * 2) : minimap.scale); const minimapMaxColumn = minimap.maxColumn | 0; - const minimapMode = minimap.mode; + const minimapSize = minimap.size; const scrollbar = options.get(EditorOption.scrollbar); const verticalScrollbarWidth = scrollbar.verticalScrollbarSize | 0; @@ -1866,7 +1866,7 @@ export class EditorLayoutInfoComputer extends ComputedEditorOption minimapCanvasInnerHeight) { + if (minimapSize === 'fill' || effectiveMinimapHeight > minimapCanvasInnerHeight) { minimapHeightIsEditorHeight = true; const configuredFontScale = minimapScale; minimapLineHeight = Math.min(lineHeight * pixelRatio, Math.max(1, Math.floor(1 / desiredRatio))); @@ -2074,7 +2074,7 @@ export interface IEditorMinimapOptions { * Control the minimap rendering mode. * Defaults to 'actual'. */ - mode?: 'actual' | 'cover' | 'contain'; + size?: 'proportional' | 'fill' | 'fit'; /** * Control the rendering of the minimap slider. * Defaults to 'mouseover'. @@ -2103,7 +2103,7 @@ class EditorMinimap extends BaseEditorOption(input.mode, this.defaultValue.mode, ['actual', 'cover', 'contain']), + size: EditorStringEnumOption.stringSet<'proportional' | 'fill' | 'fit'>(input.size, this.defaultValue.size, ['proportional', 'fill', 'fit']), side: EditorStringEnumOption.stringSet<'right' | 'left'>(input.side, this.defaultValue.side, ['right', 'left']), showSlider: EditorStringEnumOption.stringSet<'always' | 'mouseover'>(input.showSlider, this.defaultValue.showSlider, ['always', 'mouseover']), renderCharacters: EditorBooleanOption.boolean(input.renderCharacters, this.defaultValue.renderCharacters), diff --git a/src/vs/editor/test/common/viewLayout/editorLayoutProvider.test.ts b/src/vs/editor/test/common/viewLayout/editorLayoutProvider.test.ts index ff7e6ef7fbc..f9e64360021 100644 --- a/src/vs/editor/test/common/viewLayout/editorLayoutProvider.test.ts +++ b/src/vs/editor/test/common/viewLayout/editorLayoutProvider.test.ts @@ -33,7 +33,7 @@ interface IEditorLayoutProviderOpts { readonly minimapSide: 'left' | 'right'; readonly minimapRenderCharacters: boolean; readonly minimapMaxColumn: number; - minimapMode?: 'actual' | 'cover' | 'contain'; + minimapSize?: 'proportional' | 'fill' | 'fit'; readonly pixelRatio: number; } @@ -47,7 +47,7 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => { options._write(EditorOption.folding, false); const minimapOptions: EditorMinimapOptions = { enabled: input.minimap, - mode: input.minimapMode || 'actual', + size: input.minimapSize || 'proportional', side: input.minimapSide, renderCharacters: input.minimapRenderCharacters, maxColumn: input.minimapMaxColumn, @@ -978,7 +978,7 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => { minimapSide: 'right', minimapRenderCharacters: true, minimapMaxColumn: 150, - minimapMode: 'cover', + minimapSize: 'fill', pixelRatio: 2, }, { width: 1000, @@ -1042,7 +1042,7 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => { minimapSide: 'right', minimapRenderCharacters: true, minimapMaxColumn: 150, - minimapMode: 'cover', + minimapSize: 'fill', pixelRatio: 2, }, { width: 1000, @@ -1106,7 +1106,7 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => { minimapSide: 'right', minimapRenderCharacters: true, minimapMaxColumn: 150, - minimapMode: 'contain', + minimapSize: 'fit', pixelRatio: 2, }, { width: 1000, @@ -1170,7 +1170,7 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => { minimapSide: 'right', minimapRenderCharacters: true, minimapMaxColumn: 150, - minimapMode: 'contain', + minimapSize: 'fit', pixelRatio: 2, }, { width: 1000, diff --git a/src/vs/monaco.d.ts b/src/vs/monaco.d.ts index fd704b03bd3..ecb0e10c7ca 100644 --- a/src/vs/monaco.d.ts +++ b/src/vs/monaco.d.ts @@ -3444,7 +3444,7 @@ declare namespace monaco.editor { * Control the minimap rendering mode. * Defaults to 'actual'. */ - mode?: 'actual' | 'cover' | 'contain'; + size?: 'proportional' | 'fill' | 'fit'; /** * Control the rendering of the minimap slider. * Defaults to 'mouseover'. From fdfed71af4e0f1e963bf0b70e04b77580aebda91 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Thu, 27 Feb 2020 12:11:51 +0100 Subject: [PATCH 47/74] Fixes #91363 --- .../contrib/codeEditor/browser/toggleColumnSelection.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/codeEditor/browser/toggleColumnSelection.ts b/src/vs/workbench/contrib/codeEditor/browser/toggleColumnSelection.ts index fac092022e2..011918eb9b8 100644 --- a/src/vs/workbench/contrib/codeEditor/browser/toggleColumnSelection.ts +++ b/src/vs/workbench/contrib/codeEditor/browser/toggleColumnSelection.ts @@ -79,7 +79,7 @@ export class ToggleColumnSelectionAction extends Action { } const registry = Registry.as(ActionExtensions.WorkbenchActions); -registry.registerWorkbenchAction(SyncActionDescriptor.create(ToggleColumnSelectionAction, ToggleColumnSelectionAction.ID, ToggleColumnSelectionAction.LABEL), 'View: Toggle Column Selection Mode', nls.localize('view', "View")); +registry.registerWorkbenchAction(SyncActionDescriptor.create(ToggleColumnSelectionAction, ToggleColumnSelectionAction.ID, ToggleColumnSelectionAction.LABEL), 'Toggle Column Selection Mode'); MenuRegistry.appendMenuItem(MenuId.MenubarSelectionMenu, { group: '4_config', From b8dc2402a1a2c2eea53ef9820971f76df2ea07bb Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Thu, 27 Feb 2020 12:16:04 +0100 Subject: [PATCH 48/74] Fixes #91386: Improve JSON schema for minimap.scale --- src/vs/editor/common/config/editorOptions.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/vs/editor/common/config/editorOptions.ts b/src/vs/editor/common/config/editorOptions.ts index e149ea0793c..941502e43d3 100644 --- a/src/vs/editor/common/config/editorOptions.ts +++ b/src/vs/editor/common/config/editorOptions.ts @@ -2146,7 +2146,8 @@ class EditorMinimap extends BaseEditorOption Date: Thu, 27 Feb 2020 12:45:19 +0100 Subject: [PATCH 49/74] consolidate debug test instructions --- test/unit/README.md | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/test/unit/README.md b/test/unit/README.md index 4172285834f..f471ebb7d8e 100644 --- a/test/unit/README.md +++ b/test/unit/README.md @@ -9,6 +9,8 @@ All unit tests are run inside a electron-browser environment which access to DOM - use the `--debug` to see an electron window with dev tools which allows for debugging - to run only a subset of tests use the `--run` or `--glob` options +For instance, `./scripts/test.sh --debug --glob **/extHost*.test.js` runs all tests from `extHost`-files and enables you to debug them. + ## Run (inside browser) yarn test-browser --browser webkit --browser chromium @@ -24,11 +26,6 @@ Unit tests from layers `common` and `browser` are run inside `chromium`, `webkit yarn run mocha --run src/vs/editor/test/browser/controller/cursor.test.ts -## Debug - -To debug tests use `--debug` when running the test script. Also, the set of tests can be reduced with the `--run` and `--runGlob` flags. Both require a file path/pattern. Like so: - - ./scripts/test.sh --debug --runGrep **/extHost*.test.js ## Coverage From d9b345b155648314dac8b666fdede94e2dbde662 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Thu, 27 Feb 2020 12:45:08 +0100 Subject: [PATCH 50/74] Avoid having quotes inside quotes (for #91368) --- src/vs/editor/browser/services/bulkEditService.ts | 1 + src/vs/editor/contrib/rename/rename.ts | 3 ++- src/vs/workbench/services/bulkEdit/browser/bulkEditService.ts | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/vs/editor/browser/services/bulkEditService.ts b/src/vs/editor/browser/services/bulkEditService.ts index 3d18020da6f..f6fdac9c874 100644 --- a/src/vs/editor/browser/services/bulkEditService.ts +++ b/src/vs/editor/browser/services/bulkEditService.ts @@ -16,6 +16,7 @@ export interface IBulkEditOptions { progress?: IProgress; showPreview?: boolean; label?: string; + quotableLabel?: string; } export interface IBulkEditResult { diff --git a/src/vs/editor/contrib/rename/rename.ts b/src/vs/editor/contrib/rename/rename.ts index 28aba650e6a..360986dd666 100644 --- a/src/vs/editor/contrib/rename/rename.ts +++ b/src/vs/editor/contrib/rename/rename.ts @@ -206,7 +206,8 @@ class RenameController implements IEditorContribution { this._bulkEditService.apply(renameResult, { editor: this.editor, showPreview: inputFieldResult.wantsPreview, - label: nls.localize('label', "Renaming '{0}'", loc?.text) + label: nls.localize('label', "Renaming '{0}'", loc?.text), + quotableLabel: nls.localize('quotableLabel', "Renaming {0}", loc?.text), }).then(result => { if (result.ariaSummary) { alert(nls.localize('aria', "Successfully renamed '{0}' to '{1}'. Summary: {2}", loc!.text, inputFieldResult.newName, result.ariaSummary)); diff --git a/src/vs/workbench/services/bulkEdit/browser/bulkEditService.ts b/src/vs/workbench/services/bulkEdit/browser/bulkEditService.ts index e5b490f3187..dcb5a2c3346 100644 --- a/src/vs/workbench/services/bulkEdit/browser/bulkEditService.ts +++ b/src/vs/workbench/services/bulkEdit/browser/bulkEditService.ts @@ -443,7 +443,7 @@ export class BulkEditService implements IBulkEditService { // If the code editor is readonly still allow bulk edits to be applied #68549 codeEditor = undefined; } - const bulkEdit = this._instaService.createInstance(BulkEdit, options?.label, codeEditor, options?.progress, edits); + const bulkEdit = this._instaService.createInstance(BulkEdit, options?.quotableLabel || options?.label, codeEditor, options?.progress, edits); return bulkEdit.perform().then(() => { return { ariaSummary: bulkEdit.ariaMessage() }; }).catch(err => { From bde129b1deb57fd02230f79dda33d098c85946a2 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Thu, 27 Feb 2020 12:46:51 +0100 Subject: [PATCH 51/74] More tweaks to options (fixes #91368) --- src/vs/platform/undoRedo/common/undoRedoService.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vs/platform/undoRedo/common/undoRedoService.ts b/src/vs/platform/undoRedo/common/undoRedoService.ts index ccbb2c55482..8568767aa3d 100644 --- a/src/vs/platform/undoRedo/common/undoRedoService.ts +++ b/src/vs/platform/undoRedo/common/undoRedoService.ts @@ -288,8 +288,8 @@ export class UndoRedoService implements IUndoRedoService { Severity.Info, nls.localize('confirmWorkspace', "Would you like to undo '{0}' across all files?", element.label), [ - nls.localize('ok', "Undo in {0} files.", affectedEditStacks.length), - nls.localize('nok', "Undo this file."), + nls.localize('ok', "Undo In {0} Files", affectedEditStacks.length), + nls.localize('nok', "Undo This File"), nls.localize('cancel', "Cancel"), ], { From abf3b9d0ca38033c38273506a88113959d601cec Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Thu, 27 Feb 2020 12:46:10 +0100 Subject: [PATCH 52/74] continuation of #91442 --- src/vs/base/common/linkedText.ts | 4 ++-- src/vs/base/test/common/linkedText.test.ts | 10 ++++++++++ 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/src/vs/base/common/linkedText.ts b/src/vs/base/common/linkedText.ts index 65e48078110..5f6c6a05dcf 100644 --- a/src/vs/base/common/linkedText.ts +++ b/src/vs/base/common/linkedText.ts @@ -23,7 +23,7 @@ export class LinkedText { } } -const LINK_REGEX = /\[([^\]]+)\]\(((?:https?:\/\/|command:)[^\)\s]+)(?: (?:"|')([^"]+)(?:"|'))?\)/gi; +const LINK_REGEX = /\[([^\]]+)\]\(((?:https?:\/\/|command:)[^\)\s]+)(?: ("|')([^\3]+)(\3))?\)/gi; export function parseLinkedText(text: string): LinkedText { const result: LinkedTextNode[] = []; @@ -36,7 +36,7 @@ export function parseLinkedText(text: string): LinkedText { result.push(text.substring(index, match.index)); } - const [, label, href, title] = match; + const [, label, href, , title] = match; if (title) { result.push({ label, href, title }); diff --git a/src/vs/base/test/common/linkedText.test.ts b/src/vs/base/test/common/linkedText.test.ts index 15185ef44ae..a7b61a558c2 100644 --- a/src/vs/base/test/common/linkedText.test.ts +++ b/src/vs/base/test/common/linkedText.test.ts @@ -26,6 +26,16 @@ suite('LinkedText', () => { { label: 'link text', href: 'http://link.href', title: 'and a title' }, '.' ]); + assert.deepEqual(parseLinkedText('Some message with [link text](http://link.href "and a \'title\'").').nodes, [ + 'Some message with ', + { label: 'link text', href: 'http://link.href', title: 'and a \'title\'' }, + '.' + ]); + assert.deepEqual(parseLinkedText('Some message with [link text](http://link.href \'and a "title"\').').nodes, [ + 'Some message with ', + { label: 'link text', href: 'http://link.href', title: 'and a "title"' }, + '.' + ]); assert.deepEqual(parseLinkedText('Some message with [link text](random stuff).').nodes, [ 'Some message with [link text](random stuff).' ]); From 1b352f2f259856c0d82d02f0890a531b8840a8af Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Thu, 27 Feb 2020 13:01:01 +0100 Subject: [PATCH 53/74] Fixes #64459: Allow a mouse down to result in dragging the slider (when not using proportional rendering) --- src/vs/editor/browser/viewParts/minimap/minimap.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/editor/browser/viewParts/minimap/minimap.ts b/src/vs/editor/browser/viewParts/minimap/minimap.ts index 4e2808594db..ed05d886991 100644 --- a/src/vs/editor/browser/viewParts/minimap/minimap.ts +++ b/src/vs/editor/browser/viewParts/minimap/minimap.ts @@ -1111,7 +1111,7 @@ class InnerMinimap extends Disposable { if (!this._lastRenderData) { return; } - if (this._model.options.minimapHeightIsEditorHeight) { + if (this._model.options.size !== 'proportional') { if (e.leftButton && this._lastRenderData) { // pretend the click occured in the center of the slider const position = dom.getDomNodePagePosition(this._slider.domNode); From 2f8ddbe3c20f8b5152d54147895c1e559317798b Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Thu, 27 Feb 2020 12:59:49 +0100 Subject: [PATCH 54/74] notifications - revised progress indication for hidden notifications (fix #91469) --- .../notification/common/notification.ts | 7 +++ .../notifications/notificationsActions.ts | 20 ++----- .../notifications/notificationsCenter.ts | 20 +++++-- .../notifications/notificationsCommands.ts | 2 + .../notifications/notificationsToasts.ts | 39 +++++++------ src/vs/workbench/common/notifications.ts | 23 ++++++++ .../progress/browser/progressService.ts | 56 +++++++++++++++++-- .../test/common/notifications.test.ts | 11 ++++ 8 files changed, 135 insertions(+), 43 deletions(-) diff --git a/src/vs/platform/notification/common/notification.ts b/src/vs/platform/notification/common/notification.ts index a81672c8311..f7f2b5a3d9e 100644 --- a/src/vs/platform/notification/common/notification.ts +++ b/src/vs/platform/notification/common/notification.ts @@ -173,6 +173,13 @@ export interface INotificationHandle { */ readonly onDidClose: Event; + /** + * Will be fired whenever the visibility of the notification changes. + * A notification can either be visible as toast or inside the notification + * center if it is visible. + */ + readonly onDidChangeVisibility: Event; + /** * Allows to indicate progress on the notification even after the * notification is already visible. diff --git a/src/vs/workbench/browser/parts/notifications/notificationsActions.ts b/src/vs/workbench/browser/parts/notifications/notificationsActions.ts index 82301a0448e..ae63e201e24 100644 --- a/src/vs/workbench/browser/parts/notifications/notificationsActions.ts +++ b/src/vs/workbench/browser/parts/notifications/notificationsActions.ts @@ -26,10 +26,8 @@ export class ClearNotificationAction extends Action { super(id, label, 'codicon-close'); } - run(notification: INotificationViewItem): Promise { + async run(notification: INotificationViewItem): Promise { this.commandService.executeCommand(CLEAR_NOTIFICATION, notification); - - return Promise.resolve(); } } @@ -46,10 +44,8 @@ export class ClearAllNotificationsAction extends Action { super(id, label, 'codicon-clear-all'); } - run(notification: INotificationViewItem): Promise { + async run(notification: INotificationViewItem): Promise { this.commandService.executeCommand(CLEAR_ALL_NOTIFICATIONS); - - return Promise.resolve(); } } @@ -66,10 +62,8 @@ export class HideNotificationsCenterAction extends Action { super(id, label, 'codicon-chevron-down'); } - run(notification: INotificationViewItem): Promise { + async run(notification: INotificationViewItem): Promise { this.commandService.executeCommand(HIDE_NOTIFICATIONS_CENTER); - - return Promise.resolve(); } } @@ -86,10 +80,8 @@ export class ExpandNotificationAction extends Action { super(id, label, 'codicon-chevron-up'); } - run(notification: INotificationViewItem): Promise { + async run(notification: INotificationViewItem): Promise { this.commandService.executeCommand(EXPAND_NOTIFICATION, notification); - - return Promise.resolve(); } } @@ -106,10 +98,8 @@ export class CollapseNotificationAction extends Action { super(id, label, 'codicon-chevron-down'); } - run(notification: INotificationViewItem): Promise { + async run(notification: INotificationViewItem): Promise { this.commandService.executeCommand(COLLAPSE_NOTIFICATION, notification); - - return Promise.resolve(); } } diff --git a/src/vs/workbench/browser/parts/notifications/notificationsCenter.ts b/src/vs/workbench/browser/parts/notifications/notificationsCenter.ts index 094c9e1567f..c37af327a36 100644 --- a/src/vs/workbench/browser/parts/notifications/notificationsCenter.ts +++ b/src/vs/workbench/browser/parts/notifications/notificationsCenter.ts @@ -100,6 +100,9 @@ export class NotificationsCenter extends Themable implements INotificationsCente // Theming this.updateStyles(); + // Mark as visible + this.model.notifications.forEach(notification => notification.updateVisibility(true)); + // Context Key this.notificationsCenterVisibleContextKey.set(true); @@ -115,7 +118,7 @@ export class NotificationsCenter extends Themable implements INotificationsCente clearAllAction.enabled = false; } else { notificationsCenterTitle.textContent = localize('notifications', "Notifications"); - clearAllAction.enabled = true; + clearAllAction.enabled = this.model.notifications.some(notification => !notification.hasProgress); } } @@ -172,20 +175,22 @@ export class NotificationsCenter extends Themable implements INotificationsCente return; // only if visible } - let focusGroup = false; + let focusEditor = false; // Update notifications list based on event const [notificationsList, notificationsCenterContainer] = assertAllDefined(this.notificationsList, this.notificationsCenterContainer); switch (e.kind) { case NotificationChangeType.ADD: notificationsList.updateNotificationsList(e.index, 0, [e.item]); + e.item.updateVisibility(true); break; case NotificationChangeType.CHANGE: notificationsList.updateNotificationsList(e.index, 1, [e.item]); break; case NotificationChangeType.REMOVE: - focusGroup = isAncestor(document.activeElement, notificationsCenterContainer); + focusEditor = isAncestor(document.activeElement, notificationsCenterContainer); notificationsList.updateNotificationsList(e.index, 1); + e.item.updateVisibility(false); break; } @@ -197,7 +202,7 @@ export class NotificationsCenter extends Themable implements INotificationsCente this.hide(); // Restore focus to editor group if we had focus - if (focusGroup) { + if (focusEditor) { this.editorGroupService.activeGroup.focus(); } } @@ -208,13 +213,16 @@ export class NotificationsCenter extends Themable implements INotificationsCente return; // already hidden } - const focusGroup = isAncestor(document.activeElement, this.notificationsCenterContainer); + const focusEditor = isAncestor(document.activeElement, this.notificationsCenterContainer); // Hide this._isVisible = false; removeClass(this.notificationsCenterContainer, 'visible'); this.notificationsList.hide(); + // Mark as hidden + this.model.notifications.forEach(notification => notification.updateVisibility(false)); + // Context Key this.notificationsCenterVisibleContextKey.set(false); @@ -222,7 +230,7 @@ export class NotificationsCenter extends Themable implements INotificationsCente this._onDidChangeVisibility.fire(); // Restore focus to editor group if we had focus - if (focusGroup) { + if (focusEditor) { this.editorGroupService.activeGroup.focus(); } } diff --git a/src/vs/workbench/browser/parts/notifications/notificationsCommands.ts b/src/vs/workbench/browser/parts/notifications/notificationsCommands.ts index 413e700668d..b2797f261f3 100644 --- a/src/vs/workbench/browser/parts/notifications/notificationsCommands.ts +++ b/src/vs/workbench/browser/parts/notifications/notificationsCommands.ts @@ -75,6 +75,7 @@ export function registerNotificationCommands(center: INotificationsCenterControl // Show Notifications Cneter CommandsRegistry.registerCommand(SHOW_NOTIFICATIONS_CENTER, () => { + toasts.hide(); center.show(); }); @@ -92,6 +93,7 @@ export function registerNotificationCommands(center: INotificationsCenterControl if (center.isVisible) { center.hide(); } else { + toasts.hide(); center.show(); } }); diff --git a/src/vs/workbench/browser/parts/notifications/notificationsToasts.ts b/src/vs/workbench/browser/parts/notifications/notificationsToasts.ts index 95e287fbd49..ecee706fcb9 100644 --- a/src/vs/workbench/browser/parts/notifications/notificationsToasts.ts +++ b/src/vs/workbench/browser/parts/notifications/notificationsToasts.ts @@ -179,11 +179,8 @@ export class NotificationsToasts extends Themable implements INotificationsToast const toast: INotificationToast = { item, list: notificationList, container: notificationToastContainer, toast: notificationToast, toDispose: itemDisposables }; this.mapNotificationToToast.set(item, toast); - itemDisposables.add(toDisposable(() => { - if (this.isToastVisible(toast) && notificationsToastsContainer) { - notificationsToastsContainer.removeChild(toast.container); - } - })); + // When disposed, remove as visible + itemDisposables.add(toDisposable(() => this.updateToastVisibility(toast, false))); // Make visible notificationList.show(); @@ -236,6 +233,9 @@ export class NotificationsToasts extends Themable implements INotificationsToast addClass(notificationToast, 'notification-fade-in-done'); })); + // Mark as visible + item.updateVisibility(true); + // Events if (!this._isVisible) { this._isVisible = true; @@ -292,12 +292,13 @@ export class NotificationsToasts extends Themable implements INotificationsToast } private removeToast(item: INotificationViewItem): void { + let focusEditor = false; + const notificationToast = this.mapNotificationToToast.get(item); - let focusGroup = false; if (notificationToast) { const toastHasDOMFocus = isAncestor(document.activeElement, notificationToast.container); if (toastHasDOMFocus) { - focusGroup = !(this.focusNext() || this.focusPrevious()); // focus next if any, otherwise focus editor + focusEditor = !(this.focusNext() || this.focusPrevious()); // focus next if any, otherwise focus editor } // Listeners @@ -317,7 +318,7 @@ export class NotificationsToasts extends Themable implements INotificationsToast this.doHide(); // Move focus back to editor group as needed - if (focusGroup) { + if (focusEditor) { this.editorGroupService.activeGroup.focus(); } } @@ -346,11 +347,11 @@ export class NotificationsToasts extends Themable implements INotificationsToast } hide(): void { - const focusGroup = this.notificationsToastsContainer ? isAncestor(document.activeElement, this.notificationsToastsContainer) : false; + const focusEditor = this.notificationsToastsContainer ? isAncestor(document.activeElement, this.notificationsToastsContainer) : false; this.removeToasts(); - if (focusGroup) { + if (focusEditor) { this.editorGroupService.activeGroup.focus(); } } @@ -459,12 +460,12 @@ export class NotificationsToasts extends Themable implements INotificationsToast notificationToasts.push(toast); break; case ToastVisibility.HIDDEN: - if (!this.isToastVisible(toast)) { + if (!this.isToastInDOM(toast)) { notificationToasts.push(toast); } break; case ToastVisibility.VISIBLE: - if (this.isToastVisible(toast)) { + if (this.isToastInDOM(toast)) { notificationToasts.push(toast); } break; @@ -530,7 +531,7 @@ export class NotificationsToasts extends Themable implements INotificationsToast // In order to measure the client height, the element cannot have display: none toast.container.style.opacity = '0'; - this.setVisibility(toast, true); + this.updateToastVisibility(toast, true); heightToGive -= toast.container.offsetHeight; @@ -542,7 +543,7 @@ export class NotificationsToasts extends Themable implements INotificationsToast } // Hide or show toast based on context - this.setVisibility(toast, makeVisible); + this.updateToastVisibility(toast, makeVisible); toast.container.style.opacity = ''; if (makeVisible) { @@ -551,20 +552,24 @@ export class NotificationsToasts extends Themable implements INotificationsToast }); } - private setVisibility(toast: INotificationToast, visible: boolean): void { - if (this.isToastVisible(toast) === visible) { + private updateToastVisibility(toast: INotificationToast, visible: boolean): void { + if (this.isToastInDOM(toast) === visible) { return; } + // Update visibility in DOM const notificationsToastsContainer = assertIsDefined(this.notificationsToastsContainer); if (visible) { notificationsToastsContainer.appendChild(toast.container); } else { notificationsToastsContainer.removeChild(toast.container); } + + // Update visibility in model + toast.item.updateVisibility(visible); } - private isToastVisible(toast: INotificationToast): boolean { + private isToastInDOM(toast: INotificationToast): boolean { return !!toast.container.parentElement; } } diff --git a/src/vs/workbench/common/notifications.ts b/src/vs/workbench/common/notifications.ts index 73f0ef74053..809037bf68e 100644 --- a/src/vs/workbench/common/notifications.ts +++ b/src/vs/workbench/common/notifications.ts @@ -92,6 +92,9 @@ export class NotificationHandle extends Disposable implements INotificationHandl private readonly _onDidClose = this._register(new Emitter()); readonly onDidClose = this._onDidClose.event; + private readonly _onDidChangeVisibility = this._register(new Emitter()); + readonly onDidChangeVisibility = this._onDidChangeVisibility.event; + constructor(private readonly item: INotificationViewItem, private readonly onClose: (item: INotificationViewItem) => void) { super(); @@ -99,6 +102,11 @@ export class NotificationHandle extends Disposable implements INotificationHandl } private registerListeners(): void { + + // Visibility + this._register(this.item.onDidChangeVisibility(visible => this._onDidChangeVisibility.fire(visible))); + + // Closing Event.once(this.item.onDidClose)(() => { this._onDidClose.fire(); @@ -265,6 +273,7 @@ export interface INotificationViewItem { readonly onDidChangeExpansion: Event; readonly onDidClose: Event; + readonly onDidChangeVisibility: Event; readonly onDidChangeLabel: Event; expand(): void; @@ -275,6 +284,8 @@ export interface INotificationViewItem { updateMessage(message: NotificationMessage): void; updateActions(actions?: INotificationActions): void; + updateVisibility(visible: boolean): void; + close(): void; equals(item: INotificationViewItem): boolean; @@ -398,6 +409,7 @@ export class NotificationViewItem extends Disposable implements INotificationVie private static readonly MAX_MESSAGE_LENGTH = 1000; private _expanded: boolean | undefined; + private _visible: boolean = false; private _actions: INotificationActions | undefined; private _progress: NotificationViewItemProgress | undefined; @@ -411,6 +423,9 @@ export class NotificationViewItem extends Disposable implements INotificationVie private readonly _onDidChangeLabel = this._register(new Emitter()); readonly onDidChangeLabel = this._onDidChangeLabel.event; + private readonly _onDidChangeVisibility = this._register(new Emitter()); + readonly onDidChangeVisibility = this._onDidChangeVisibility.event; + static create(notification: INotification, filter: NotificationsFilter = NotificationsFilter.OFF): INotificationViewItem | undefined { if (!notification || !notification.message || isPromiseCanceledError(notification.message)) { return undefined; // we need a message to show @@ -600,6 +615,14 @@ export class NotificationViewItem extends Disposable implements INotificationVie this._onDidChangeLabel.fire({ kind: NotificationViewItemLabelKind.ACTIONS }); } + updateVisibility(visible: boolean): void { + if (this._visible !== visible) { + this._visible = visible; + + this._onDidChangeVisibility.fire(visible); + } + } + expand(): void { if (this._expanded || !this.canCollapse) { return; diff --git a/src/vs/workbench/services/progress/browser/progressService.ts b/src/vs/workbench/services/progress/browser/progressService.ts index 6d4723b34e3..e0b2980aad4 100644 --- a/src/vs/workbench/services/progress/browser/progressService.ts +++ b/src/vs/workbench/services/progress/browser/progressService.ts @@ -6,7 +6,7 @@ import 'vs/css!./media/progressService'; import { localize } from 'vs/nls'; -import { IDisposable, dispose, DisposableStore, MutableDisposable, Disposable } from 'vs/base/common/lifecycle'; +import { IDisposable, dispose, DisposableStore, MutableDisposable, Disposable, toDisposable } from 'vs/base/common/lifecycle'; import { IProgressService, IProgressOptions, IProgressStep, ProgressLocation, IProgress, Progress, IProgressCompositeOptions, IProgressNotificationOptions, IProgressRunner, IProgressIndicator, IProgressWindowOptions } from 'vs/platform/progress/common/progress'; import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet'; import { StatusbarAlignment, IStatusbarService } from 'vs/workbench/services/statusbar/common/statusbar'; @@ -191,6 +191,38 @@ export class ProgressService extends Disposable implements IProgressService { } }; + const createWindowProgress = () => { + + // Create a promise that we can resolve as needed + // when the outside calls dispose on us + let promiseResolve: () => void; + const promise = new Promise(resolve => promiseResolve = resolve); + + this.withWindowProgress({ + location: ProgressLocation.Window, + title: options.title, + command: 'notifications.showList' + }, progress => { + + // Apply any progress that was made already + if (progressStateModel.step) { + progress.report(progressStateModel.step); + } + + // Continue to report progress as it happens + const onDidReportListener = progressStateModel.onDidReport(step => progress.report(step)); + promise.finally(() => onDidReportListener.dispose()); + + // When the progress model gets disposed, we are done as well + Event.once(progressStateModel.onDispose)(() => promiseResolve()); + + return promise; + }); + + // Dispose means completing our promise + return toDisposable(() => promiseResolve()); + }; + const createNotification = (message: string, increment?: number): INotificationHandle => { const notificationDisposables = new DisposableStore(); @@ -229,7 +261,7 @@ export class ProgressService extends Disposable implements IProgressService { primaryActions.push(cancelAction); } - const handle = this.notificationService.notify({ + const notification = this.notificationService.notify({ severity: Severity.Info, message, source: options.source, @@ -237,12 +269,26 @@ export class ProgressService extends Disposable implements IProgressService { progress: typeof increment === 'number' && increment >= 0 ? { total: 100, worked: increment } : { infinite: true } }); - updateProgress(handle, increment); + // Switch to window based progress once the notification + // changes visibility to hidden and is still ongoing. + // Remove that window based progress once the notification + // shows again. + let windowProgressDisposable: IDisposable | undefined = undefined; + notificationDisposables.add(notification.onDidChangeVisibility(visible => { + + // Clear any previous running window progress + dispose(windowProgressDisposable); + + // Create new window progress if notification got hidden + if (!visible && !progressStateModel.done) { + windowProgressDisposable = createWindowProgress(); + } + })); // Clear upon dispose - Event.once(handle.onDidClose)(() => notificationDisposables.dispose()); + Event.once(notification.onDidClose)(() => notificationDisposables.dispose()); - return handle; + return notification; }; const updateProgress = (notification: INotificationHandle, increment?: number): void => { diff --git a/src/vs/workbench/test/common/notifications.test.ts b/src/vs/workbench/test/common/notifications.test.ts index 7eefd25cb8e..a050bc29422 100644 --- a/src/vs/workbench/test/common/notifications.test.ts +++ b/src/vs/workbench/test/common/notifications.test.ts @@ -98,6 +98,17 @@ suite('Notifications', () => { assert.equal(called, 1); + called = 0; + item1.onDidChangeVisibility(e => { + called++; + }); + + item1.updateVisibility(true); + item1.updateVisibility(false); + item1.updateVisibility(false); + + assert.equal(called, 2); + called = 0; item1.onDidClose(() => { called++; From f9b397429954f2bdae755a0eea2b3bc1b40c3f9e Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Thu, 27 Feb 2020 13:13:33 +0100 Subject: [PATCH 55/74] notifications - handle markdown links in status bar --- .../services/progress/browser/progressService.ts | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/vs/workbench/services/progress/browser/progressService.ts b/src/vs/workbench/services/progress/browser/progressService.ts index e0b2980aad4..2f464fb7405 100644 --- a/src/vs/workbench/services/progress/browser/progressService.ts +++ b/src/vs/workbench/services/progress/browser/progressService.ts @@ -24,6 +24,7 @@ import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent'; import { EventHelper } from 'vs/base/browser/dom'; import { IPanelService } from 'vs/workbench/services/panel/common/panelService'; +import { parseLinkedText } from 'vs/base/common/linkedText'; export class ProgressService extends Disposable implements IProgressService { @@ -200,17 +201,25 @@ export class ProgressService extends Disposable implements IProgressService { this.withWindowProgress({ location: ProgressLocation.Window, - title: options.title, + title: options.title ? parseLinkedText(options.title).toString() : undefined, // convert markdown links => string command: 'notifications.showList' }, progress => { + function reportProgress(step: IProgressStep) { + if (step.message) { + progress.report({ + message: parseLinkedText(step.message).toString() // convert markdown links => string + }); + } + } + // Apply any progress that was made already if (progressStateModel.step) { - progress.report(progressStateModel.step); + reportProgress(progressStateModel.step); } // Continue to report progress as it happens - const onDidReportListener = progressStateModel.onDidReport(step => progress.report(step)); + const onDidReportListener = progressStateModel.onDidReport(step => reportProgress(step)); promise.finally(() => onDidReportListener.dispose()); // When the progress model gets disposed, we are done as well From 4f232ba78f3d7dc673fc2f5bbd041cf990987b67 Mon Sep 17 00:00:00 2001 From: Andre Weinand Date: Thu, 27 Feb 2020 13:15:30 +0100 Subject: [PATCH 56/74] improve documentation for debug hover API; fxes #91404 --- src/vs/vscode.d.ts | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/vs/vscode.d.ts b/src/vs/vscode.d.ts index 207183cb8d8..cbf69745888 100644 --- a/src/vs/vscode.d.ts +++ b/src/vs/vscode.d.ts @@ -2495,16 +2495,18 @@ declare module 'vscode' { /** * The evaluatable expression provider interface defines the contract between extensions and - * the debug hover. + * the debug hover. In this contract the provider returns an evaluatable expression for a given position + * in a document and VS Code evaluates this expression in the active debug session and shows the result in a debug hover. */ export interface EvaluatableExpressionProvider { /** * Provide an evaluatable expression for the given document and position. + * VS Code will evaluate this expression in the active debug session and will show the result in the debug hover. * The expression can be implicitly specified by the range in the underlying document or by explicitly returning an expression. * - * @param document The document in which the debug hover is opened. - * @param position The position in the document where the debug hover is opened. + * @param document The document for which the debug hover is about to appear. + * @param position The line and character position in the document where the debug hover is about to appear. * @param token A cancellation token. * @return An EvaluatableExpression or a thenable that resolves to such. The lack of a result can be * signaled by returning `undefined` or `null`. @@ -9174,6 +9176,7 @@ declare module 'vscode' { /** * Register a provider that locates evaluatable expressions in text documents. + * VS Code will evaluate the expression in the active debug session and will show the result in the debug hover. * * If multiple providers are registered for a language an arbitrary provider will be used. * From 0bab257fe5d087a7064b4ffeeb30827e4ce8a67a Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Thu, 27 Feb 2020 14:22:23 +0100 Subject: [PATCH 57/74] smoke - remove firefox from docs --- test/smoke/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/smoke/README.md b/test/smoke/README.md index 8b41d05ed08..7bec799f89d 100644 --- a/test/smoke/README.md +++ b/test/smoke/README.md @@ -13,13 +13,13 @@ yarn --cwd test/automation yarn smoketest # Dev (Web) -yarn smoketest --web --browser [chromium|firefox|webkit] +yarn smoketest --web --browser [chromium|webkit] # Build (Electron) yarn smoketest --build --stable-build # Build (Web - read instructions below) -yarn smoketest --build --web --browser [chromium|firefox|webkit] +yarn smoketest --build --web --browser [chromium|webkit] # Remote (Electron) yarn smoketest --build --remote From fbb020867f97d7f08cf00e9e9156c10a3bebe817 Mon Sep 17 00:00:00 2001 From: Alex Ross Date: Thu, 27 Feb 2020 14:53:37 +0100 Subject: [PATCH 58/74] File schema check was deleted from simple file dialog Paritally reverts commit 5dfa261ceddacf93eefc9612e48b170f3ee8bbf0 Fixes #91687 --- .../services/dialogs/browser/simpleFileDialog.ts | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/services/dialogs/browser/simpleFileDialog.ts b/src/vs/workbench/services/dialogs/browser/simpleFileDialog.ts index e9e8c8fff36..58c9355d126 100644 --- a/src/vs/workbench/services/dialogs/browser/simpleFileDialog.ts +++ b/src/vs/workbench/services/dialogs/browser/simpleFileDialog.ts @@ -156,7 +156,7 @@ export class SimpleFileDialog { public async showOpenDialog(options: IOpenDialogOptions = {}): Promise { this.scheme = this.getScheme(options.availableFileSystems, options.defaultUri); - this.userHome = await this.remotePathService.userHome; + this.userHome = await this.getUserHome(); const newOptions = this.getOptions(options); if (!newOptions) { return Promise.resolve(undefined); @@ -167,7 +167,7 @@ export class SimpleFileDialog { public async showSaveDialog(options: ISaveDialogOptions): Promise { this.scheme = this.getScheme(options.availableFileSystems, options.defaultUri); - this.userHome = await this.remotePathService.userHome; + this.userHome = await this.getUserHome(); this.requiresTrailing = true; const newOptions = this.getOptions(options, true); if (!newOptions) { @@ -231,6 +231,13 @@ export class SimpleFileDialog { return this.remoteAgentEnvironment; } + private async getUserHome(): Promise { + if (this.scheme !== Schemas.file) { + return this.remotePathService.userHome; + } + return URI.from({ scheme: this.scheme, path: this.environmentService.userHome }); + } + private async pickResource(isSave: boolean = false): Promise { this.allowFolderSelection = !!this.options.canSelectFolders; this.allowFileSelection = !!this.options.canSelectFiles; From 6a0b43c06222efa199cb1854f957608736647708 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Thu, 27 Feb 2020 15:10:18 +0100 Subject: [PATCH 59/74] Fixes #91644 --- src/vs/editor/browser/widget/diffReview.ts | 23 ++++++++++++++----- .../browser/widget/media/diffReview.css | 9 ++++---- 2 files changed, 22 insertions(+), 10 deletions(-) diff --git a/src/vs/editor/browser/widget/diffReview.ts b/src/vs/editor/browser/widget/diffReview.ts index cfa24de682f..2da217bb864 100644 --- a/src/vs/editor/browser/widget/diffReview.ts +++ b/src/vs/editor/browser/widget/diffReview.ts @@ -617,10 +617,11 @@ export class DiffReview extends Disposable { header.setAttribute('role', 'listitem'); container.appendChild(header); + const lineHeight = modifiedOptions.get(EditorOption.lineHeight); let modLine = minModifiedLine; for (let i = 0, len = diffs.length; i < len; i++) { const diffEntry = diffs[i]; - DiffReview._renderSection(container, diffEntry, modLine, this._width, originalOptions, originalModel, originalModelOpts, modifiedOptions, modifiedModel, modifiedModelOpts); + DiffReview._renderSection(container, diffEntry, modLine, lineHeight, this._width, originalOptions, originalModel, originalModelOpts, modifiedOptions, modifiedModel, modifiedModelOpts); if (diffEntry.modifiedLineStart !== 0) { modLine = diffEntry.modifiedLineEnd; } @@ -632,7 +633,7 @@ export class DiffReview extends Disposable { } private static _renderSection( - dest: HTMLElement, diffEntry: DiffEntry, modLine: number, width: number, + dest: HTMLElement, diffEntry: DiffEntry, modLine: number, lineHeight: number, width: number, originalOptions: IComputedEditorOptions, originalModel: ITextModel, originalModelOpts: TextModelResolvedOptions, modifiedOptions: IComputedEditorOptions, modifiedModel: ITextModel, modifiedModelOpts: TextModelResolvedOptions ): void { @@ -641,17 +642,18 @@ export class DiffReview extends Disposable { let rowClassName: string = 'diff-review-row'; let lineNumbersExtraClassName: string = ''; - let spacerClassName: string = 'diff-review-spacer'; + const spacerClassName: string = 'diff-review-spacer'; + let spacerCodiconName: string | null = null; switch (type) { case DiffEntryType.Insert: rowClassName = 'diff-review-row line-insert'; lineNumbersExtraClassName = ' char-insert'; - spacerClassName = 'diff-review-spacer insert-sign'; + spacerCodiconName = 'codicon codicon-add'; break; case DiffEntryType.Delete: rowClassName = 'diff-review-row line-delete'; lineNumbersExtraClassName = ' char-delete'; - spacerClassName = 'diff-review-spacer delete-sign'; + spacerCodiconName = 'codicon codicon-remove'; break; } @@ -686,6 +688,7 @@ export class DiffReview extends Disposable { let cell = document.createElement('div'); cell.className = 'diff-review-cell'; + cell.style.height = `${lineHeight}px`; row.appendChild(cell); const originalLineNumber = document.createElement('span'); @@ -713,7 +716,15 @@ export class DiffReview extends Disposable { const spacer = document.createElement('span'); spacer.className = spacerClassName; - spacer.innerHTML = '  '; + + if (spacerCodiconName) { + const spacerCodicon = document.createElement('span'); + spacerCodicon.className = spacerCodiconName; + spacerCodicon.innerHTML = '  '; + spacer.appendChild(spacerCodicon); + } else { + spacer.innerHTML = '  '; + } cell.appendChild(spacer); let lineContent: string; diff --git a/src/vs/editor/browser/widget/media/diffReview.css b/src/vs/editor/browser/widget/media/diffReview.css index b2b17028489..56c6f15cbf6 100644 --- a/src/vs/editor/browser/widget/media/diffReview.css +++ b/src/vs/editor/browser/widget/media/diffReview.css @@ -37,13 +37,14 @@ width: 100%; } -.monaco-diff-editor .diff-review-cell { - display: table-cell; -} - .monaco-diff-editor .diff-review-spacer { display: inline-block; width: 10px; + vertical-align: middle; +} + +.monaco-diff-editor .diff-review-spacer > .codicon { + font-size: 9px !important; } .monaco-diff-editor .diff-review-actions { From 9e8d88b23277a1bd255327caba881e6358159a89 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Thu, 27 Feb 2020 16:06:41 +0100 Subject: [PATCH 60/74] Fixes #91460 --- src/vs/editor/common/controller/cursor.ts | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/vs/editor/common/controller/cursor.ts b/src/vs/editor/common/controller/cursor.ts index 883abf19c6d..d1dc46b0a16 100644 --- a/src/vs/editor/common/controller/cursor.ts +++ b/src/vs/editor/common/controller/cursor.ts @@ -430,15 +430,14 @@ export class Cursor extends viewEvents.ViewEventEmitter implements ICursors { return this._columnSelectData; } const primaryCursor = this._cursors.getPrimaryCursor(); - const primaryPos = primaryCursor.viewState.selectionStart.getStartPosition(); - const viewLineNumber = primaryPos.lineNumber; - const viewVisualColumn = CursorColumns.visibleColumnFromColumn2(this.context.config, this.context.viewModel, primaryPos); + const viewSelectionStart = primaryCursor.viewState.selectionStart.getStartPosition(); + const viewPosition = primaryCursor.viewState.position; return { isReal: false, - fromViewLineNumber: viewLineNumber, - fromViewVisualColumn: viewVisualColumn, - toViewLineNumber: viewLineNumber, - toViewVisualColumn: viewVisualColumn, + fromViewLineNumber: viewSelectionStart.lineNumber, + fromViewVisualColumn: CursorColumns.visibleColumnFromColumn2(this.context.config, this.context.viewModel, viewSelectionStart), + toViewLineNumber: viewPosition.lineNumber, + toViewVisualColumn: CursorColumns.visibleColumnFromColumn2(this.context.config, this.context.viewModel, viewPosition), }; } From 684e2399e04a3af0b40ab4b753fbb837452253eb Mon Sep 17 00:00:00 2001 From: SteVen Batten Date: Thu, 27 Feb 2020 08:00:01 -0800 Subject: [PATCH 61/74] remove from cmd palette fixes #91423 --- src/vs/workbench/browser/actions/layoutActions.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/browser/actions/layoutActions.ts b/src/vs/workbench/browser/actions/layoutActions.ts index 0ece351afc3..5cde8dd380a 100644 --- a/src/vs/workbench/browser/actions/layoutActions.ts +++ b/src/vs/workbench/browser/actions/layoutActions.ts @@ -613,7 +613,7 @@ export class MoveFocusedViewAction extends Action { } } -registry.registerWorkbenchAction(SyncActionDescriptor.create(MoveFocusedViewAction, MoveFocusedViewAction.ID, MoveFocusedViewAction.LABEL), 'View: Move Focused View', viewCategory); +registry.registerWorkbenchAction(SyncActionDescriptor.create(MoveFocusedViewAction, MoveFocusedViewAction.ID, MoveFocusedViewAction.LABEL), 'View: Move Focused View', viewCategory, FocusedViewContext.notEqualsTo('')); // --- Resize View From d983fe60149c8c82782313c3a3e85a215c8fecda Mon Sep 17 00:00:00 2001 From: Eric Amodio Date: Tue, 25 Feb 2020 11:40:13 -0500 Subject: [PATCH 62/74] Fixes bad encoding in title - ref #91377 --- extensions/git/src/commands.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extensions/git/src/commands.ts b/extensions/git/src/commands.ts index 10d2cfc2d5b..a27fa783fc0 100644 --- a/extensions/git/src/commands.ts +++ b/extensions/git/src/commands.ts @@ -2357,7 +2357,7 @@ export class CommandCenter { else if (item.previousRef === 'HEAD' && item.ref === '~') { title = localize('git.title.index', '{0} (Index)', basename); } else { - title = localize('git.title.diffRefs', '{0} ({1}) \u27f7 {0} ({2})', basename, item.shortPreviousRef, item.shortRef); + title = localize('git.title.diffRefs', '{0} ({1}) ⟷ {0} ({2})', basename, item.shortPreviousRef, item.shortRef); } return commands.executeCommand('vscode.diff', toGitUri(uri, item.previousRef), item.ref === '' ? uri : toGitUri(uri, item.ref), title); From 5acdde478f2911d6f375b56ad00e267cc8beaf4f Mon Sep 17 00:00:00 2001 From: Eric Amodio Date: Thu, 27 Feb 2020 11:23:23 -0500 Subject: [PATCH 63/74] Fixes #91677 --- .../contrib/timeline/browser/timelinePane.ts | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/contrib/timeline/browser/timelinePane.ts b/src/vs/workbench/contrib/timeline/browser/timelinePane.ts index d438a1b739c..29dceaaca3d 100644 --- a/src/vs/workbench/contrib/timeline/browser/timelinePane.ts +++ b/src/vs/workbench/contrib/timeline/browser/timelinePane.ts @@ -251,7 +251,7 @@ export class TimelinePane extends ViewPane { } this._tree.setChildren(null, undefined); - this.message = localize('timeline.loading', 'Loading timeline for ${0}...', basename(uri.fsPath)); + this.message = localize('timeline.loading', 'Loading timeline for {0}...', basename(uri.fsPath)); }, 500, this._uri); } } @@ -291,7 +291,7 @@ export class TimelinePane extends ViewPane { if (!reset) { // TODO: Handle pending request - if (cursors?.more === false) { + if (cursors?.more !== true) { continue; } @@ -306,6 +306,10 @@ export class TimelinePane extends ViewPane { request?.tokenSource ?? new CancellationTokenSource(), { cacheResults: true } )!; + if (request === undefined) { + continue; + } + this._pendingRequests.set(source, request); if (!reusingToken) { request.tokenSource.token.onCancellationRequested(() => this._pendingRequests.delete(source)); @@ -322,6 +326,10 @@ export class TimelinePane extends ViewPane { new CancellationTokenSource(), { cacheResults: true } )!; + if (request === undefined) { + continue; + } + this._pendingRequests.set(source, request); request.tokenSource.token.onCancellationRequested(() => this._pendingRequests.delete(source)); } From bddc5ef7019edf0a1c2d8be9ba2cba832cd614cb Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Thu, 27 Feb 2020 17:54:17 +0100 Subject: [PATCH 64/74] Fix #91486 --- src/vs/platform/environment/node/environmentService.ts | 2 +- src/vs/platform/userDataSync/common/abstractSynchronizer.ts | 2 +- .../services/environment/browser/environmentService.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/vs/platform/environment/node/environmentService.ts b/src/vs/platform/environment/node/environmentService.ts index 0428e1e888a..15b5c20cbbf 100644 --- a/src/vs/platform/environment/node/environmentService.ts +++ b/src/vs/platform/environment/node/environmentService.ts @@ -112,7 +112,7 @@ export class EnvironmentService implements IEnvironmentService { get settingsResource(): URI { return resources.joinPath(this.userRoamingDataHome, 'settings.json'); } @memoize - get userDataSyncHome(): URI { return resources.joinPath(this.userRoamingDataHome, '.sync'); } + get userDataSyncHome(): URI { return resources.joinPath(this.userRoamingDataHome, 'sync'); } @memoize get settingsSyncPreviewResource(): URI { return resources.joinPath(this.userDataSyncHome, 'settings.json'); } diff --git a/src/vs/platform/userDataSync/common/abstractSynchronizer.ts b/src/vs/platform/userDataSync/common/abstractSynchronizer.ts index 92590672d67..0dcf03eebde 100644 --- a/src/vs/platform/userDataSync/common/abstractSynchronizer.ts +++ b/src/vs/platform/userDataSync/common/abstractSynchronizer.ts @@ -68,7 +68,7 @@ export abstract class AbstractSynchroniser extends Disposable { ) { super(); this.syncFolder = joinPath(environmentService.userDataSyncHome, source); - this.lastSyncResource = joinPath(this.syncFolder, `.lastSync${source}.json`); + this.lastSyncResource = joinPath(this.syncFolder, `lastSync${source}.json`); this.cleanUpDelayer = new ThrottledDelayer(50); this.cleanUpBackup(); } diff --git a/src/vs/workbench/services/environment/browser/environmentService.ts b/src/vs/workbench/services/environment/browser/environmentService.ts index b7ee69dc594..c94ee4e88cf 100644 --- a/src/vs/workbench/services/environment/browser/environmentService.ts +++ b/src/vs/workbench/services/environment/browser/environmentService.ts @@ -137,7 +137,7 @@ export class BrowserWorkbenchEnvironmentService implements IWorkbenchEnvironment get argvResource(): URI { return joinPath(this.userRoamingDataHome, 'argv.json'); } @memoize - get userDataSyncHome(): URI { return joinPath(this.userRoamingDataHome, '.sync'); } + get userDataSyncHome(): URI { return joinPath(this.userRoamingDataHome, 'sync'); } @memoize get settingsSyncPreviewResource(): URI { return joinPath(this.userDataSyncHome, 'settings.json'); } From b77929959cb3e0b13d669fb7f711bca77ac7ff02 Mon Sep 17 00:00:00 2001 From: Rachel Macfarlane Date: Thu, 27 Feb 2020 10:12:12 -0800 Subject: [PATCH 65/74] Log additional information when getting auth token --- extensions/vscode-account/src/AADHelper.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/extensions/vscode-account/src/AADHelper.ts b/extensions/vscode-account/src/AADHelper.ts index b1aee3e6bdf..16e7990be0b 100644 --- a/extensions/vscode-account/src/AADHelper.ts +++ b/extensions/vscode-account/src/AADHelper.ts @@ -192,7 +192,9 @@ export class AzureActiveDirectoryService { private async resolveAccessToken(token: IToken): Promise { if (token.accessToken && (!token.expiresAt || token.expiresAt > Date.now())) { - Logger.info('Token available from cache'); + token.expiresAt + ? Logger.info(`Token available from cache, expires in ${token.expiresAt - Date.now()} milliseconds`) + : Logger.info('Token available from cache'); return Promise.resolve(token.accessToken); } From d7a42153287b9c7f3da8a8fcbe01925c7d783565 Mon Sep 17 00:00:00 2001 From: Pine Wu Date: Thu, 27 Feb 2020 10:47:40 -0800 Subject: [PATCH 66/74] Fix #90552 --- src/vs/editor/contrib/suggest/media/suggest.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/editor/contrib/suggest/media/suggest.css b/src/vs/editor/contrib/suggest/media/suggest.css index 875769452fa..af01d6da5c5 100644 --- a/src/vs/editor/contrib/suggest/media/suggest.css +++ b/src/vs/editor/contrib/suggest/media/suggest.css @@ -234,7 +234,7 @@ flex-shrink: 0; } .monaco-editor .suggest-widget .monaco-list .monaco-list-row:not(.string-label) > .contents > .main > .left > .monaco-icon-label { - max-width: 80%; + max-width: 100%; } .monaco-editor .suggest-widget .monaco-list .monaco-list-row.string-label > .contents > .main > .left > .monaco-icon-label { flex-shrink: 1; From 9c70b061384794c1755a959d0cace6191ee4f300 Mon Sep 17 00:00:00 2001 From: Pine Wu Date: Thu, 27 Feb 2020 10:51:15 -0800 Subject: [PATCH 67/74] Revert "Fix #90552" This reverts commit d7a42153287b9c7f3da8a8fcbe01925c7d783565. --- src/vs/editor/contrib/suggest/media/suggest.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/editor/contrib/suggest/media/suggest.css b/src/vs/editor/contrib/suggest/media/suggest.css index af01d6da5c5..875769452fa 100644 --- a/src/vs/editor/contrib/suggest/media/suggest.css +++ b/src/vs/editor/contrib/suggest/media/suggest.css @@ -234,7 +234,7 @@ flex-shrink: 0; } .monaco-editor .suggest-widget .monaco-list .monaco-list-row:not(.string-label) > .contents > .main > .left > .monaco-icon-label { - max-width: 100%; + max-width: 80%; } .monaco-editor .suggest-widget .monaco-list .monaco-list-row.string-label > .contents > .main > .left > .monaco-icon-label { flex-shrink: 1; From d87d03311db5abe1e301f038ebd83e02add658ea Mon Sep 17 00:00:00 2001 From: Pine Wu Date: Thu, 27 Feb 2020 10:51:39 -0800 Subject: [PATCH 68/74] Fix #90865 --- src/vs/editor/contrib/suggest/media/suggest.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/editor/contrib/suggest/media/suggest.css b/src/vs/editor/contrib/suggest/media/suggest.css index 875769452fa..af01d6da5c5 100644 --- a/src/vs/editor/contrib/suggest/media/suggest.css +++ b/src/vs/editor/contrib/suggest/media/suggest.css @@ -234,7 +234,7 @@ flex-shrink: 0; } .monaco-editor .suggest-widget .monaco-list .monaco-list-row:not(.string-label) > .contents > .main > .left > .monaco-icon-label { - max-width: 80%; + max-width: 100%; } .monaco-editor .suggest-widget .monaco-list .monaco-list-row.string-label > .contents > .main > .left > .monaco-icon-label { flex-shrink: 1; From a35a8a2acf6f067de9fca2a2526659f4e50b1b01 Mon Sep 17 00:00:00 2001 From: Pine Wu Date: Thu, 27 Feb 2020 11:03:48 -0800 Subject: [PATCH 69/74] Fix #89772 --- src/vs/editor/common/config/editorOptions.ts | 23 +++++++++++++------ .../editor/contrib/suggest/suggestWidget.ts | 2 +- src/vs/monaco.d.ts | 9 ++++++-- 3 files changed, 24 insertions(+), 10 deletions(-) diff --git a/src/vs/editor/common/config/editorOptions.ts b/src/vs/editor/common/config/editorOptions.ts index 941502e43d3..284c6f904bb 100644 --- a/src/vs/editor/common/config/editorOptions.ts +++ b/src/vs/editor/common/config/editorOptions.ts @@ -2835,9 +2835,14 @@ export interface ISuggestOptions { */ showSnippets?: boolean; /** - * Controls the visibility of the status bar at the bottom of the suggest widget. + * Status bar related settings. */ - hideStatusBar?: boolean; + statusBar?: { + /** + * Controls the visibility of the status bar at the bottom of the suggest widget. + */ + visible?: boolean; + } } export type InternalSuggestOptions = Readonly>; @@ -2879,7 +2884,9 @@ class EditorSuggest extends BaseEditorOption toggleClass(this.element, 'with-status-bar', !this.editor.getOption(EditorOption.suggest).hideStatusBar); + const applyStatusBarStyle = () => toggleClass(this.element, 'with-status-bar', this.editor.getOption(EditorOption.suggest).statusBar.visible); applyStatusBarStyle(); this.statusBarElement = append(this.element, $('.suggest-status-bar')); diff --git a/src/vs/monaco.d.ts b/src/vs/monaco.d.ts index ecb0e10c7ca..543ac0ca086 100644 --- a/src/vs/monaco.d.ts +++ b/src/vs/monaco.d.ts @@ -3754,9 +3754,14 @@ declare namespace monaco.editor { */ showSnippets?: boolean; /** - * Controls the visibility of the status bar at the bottom of the suggest widget. + * Status bar related settings. */ - hideStatusBar?: boolean; + statusBar?: { + /** + * Controls the visibility of the status bar at the bottom of the suggest widget. + */ + visible?: boolean; + }; } export type InternalSuggestOptions = Readonly>; From 06529506b21c87ac276272041bc1cf586c25dcde Mon Sep 17 00:00:00 2001 From: Connor Peet Date: Thu, 27 Feb 2020 11:04:51 -0800 Subject: [PATCH 70/74] debug: update js-debug-nightly to "2020.2.2617" @ 2020-02-27T01:06:21.78Z --- build/builtInExtensions.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/builtInExtensions.json b/build/builtInExtensions.json index ddc65ea119f..bd9188f8ee1 100644 --- a/build/builtInExtensions.json +++ b/build/builtInExtensions.json @@ -46,7 +46,7 @@ }, { "name": "ms-vscode.js-debug-nightly", - "version": "2020.2.2517", + "version": "2020.2.2617", "forQualities": [ "insider" ], From 8ef18acdaf4502e3b81efc498036b432e925df04 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Thu, 27 Feb 2020 11:55:33 -0800 Subject: [PATCH 71/74] Don't require return value backup Fixes #91703 All custom editors should implement backup or throw an exception if they cannot for some reason. --- src/vs/vscode.proposed.d.ts | 2 +- src/vs/workbench/api/common/extHost.protocol.ts | 2 +- src/vs/workbench/api/common/extHostWebview.ts | 2 +- .../contrib/customEditor/common/customEditor.ts | 2 +- .../contrib/customEditor/common/customEditorModel.ts | 12 ++++++++---- 5 files changed, 12 insertions(+), 8 deletions(-) diff --git a/src/vs/vscode.proposed.d.ts b/src/vs/vscode.proposed.d.ts index 6c28f957862..15474e3339a 100644 --- a/src/vs/vscode.proposed.d.ts +++ b/src/vs/vscode.proposed.d.ts @@ -1273,7 +1273,7 @@ declare module 'vscode' { * in an operation that takes time to complete, your extension may decide to finish the ongoing backup rather * than cancelling it to ensure that VS Code has some valid backup. */ - backup(cancellation: CancellationToken): Thenable; + backup(cancellation: CancellationToken): Thenable; } /** diff --git a/src/vs/workbench/api/common/extHost.protocol.ts b/src/vs/workbench/api/common/extHost.protocol.ts index a54b3d0766a..10f51d23548 100644 --- a/src/vs/workbench/api/common/extHost.protocol.ts +++ b/src/vs/workbench/api/common/extHost.protocol.ts @@ -620,7 +620,7 @@ export interface ExtHostWebviewsShape { $onSave(resource: UriComponents, viewType: string): Promise; $onSaveAs(resource: UriComponents, viewType: string, targetResource: UriComponents): Promise; - $backup(resource: UriComponents, viewType: string, cancellation: CancellationToken): Promise; + $backup(resource: UriComponents, viewType: string, cancellation: CancellationToken): Promise; } export interface MainThreadUrlsShape extends IDisposable { diff --git a/src/vs/workbench/api/common/extHostWebview.ts b/src/vs/workbench/api/common/extHostWebview.ts index 539f31df1c2..cfac95a00b3 100644 --- a/src/vs/workbench/api/common/extHostWebview.ts +++ b/src/vs/workbench/api/common/extHostWebview.ts @@ -727,7 +727,7 @@ export class ExtHostWebviews implements ExtHostWebviewsShape { return document._saveAs(URI.revive(targetResource)); } - async $backup(resourceComponents: UriComponents, viewType: string, cancellation: CancellationToken): Promise { + async $backup(resourceComponents: UriComponents, viewType: string, cancellation: CancellationToken): Promise { const document = this.getDocument(viewType, resourceComponents); return document._backup(cancellation); } diff --git a/src/vs/workbench/contrib/customEditor/common/customEditor.ts b/src/vs/workbench/contrib/customEditor/common/customEditor.ts index a0e84261e3a..f14ffcf0a81 100644 --- a/src/vs/workbench/contrib/customEditor/common/customEditor.ts +++ b/src/vs/workbench/contrib/customEditor/common/customEditor.ts @@ -74,7 +74,7 @@ export interface ICustomEditorModel extends IWorkingCopy { readonly onWillSave: Event; readonly onWillSaveAs: Event; - onBackup(f: () => CancelablePromise): void; + onBackup(f: () => CancelablePromise): void; setDirty(dirty: boolean): void; undo(): void; diff --git a/src/vs/workbench/contrib/customEditor/common/customEditorModel.ts b/src/vs/workbench/contrib/customEditor/common/customEditorModel.ts index 6adac4c6199..43f887a82a0 100644 --- a/src/vs/workbench/contrib/customEditor/common/customEditorModel.ts +++ b/src/vs/workbench/contrib/customEditor/common/customEditorModel.ts @@ -29,7 +29,7 @@ namespace HotExitState { readonly type = Type.Pending; constructor( - public readonly operation: CancelablePromise, + public readonly operation: CancelablePromise, ) { } } @@ -90,9 +90,9 @@ export class CustomEditorModel extends Disposable implements ICustomEditorModel private readonly _onWillSaveAs = this._register(new Emitter()); public readonly onWillSaveAs = this._onWillSaveAs.event; - private _onBackup: undefined | (() => CancelablePromise); + private _onBackup: undefined | (() => CancelablePromise); - public onBackup(f: () => CancelablePromise) { + public onBackup(f: () => CancelablePromise) { if (this._onBackup) { throw new Error('Backup already implemented'); } @@ -182,7 +182,11 @@ export class CustomEditorModel extends Disposable implements ICustomEditorModel this._hotExitState = pendingState; try { - this._hotExitState = await pendingState.operation ? HotExitState.Allowed : HotExitState.NotAllowed; + await pendingState.operation; + // Make sure state has not changed in the meantime + if (this._hotExitState === pendingState) { + this._hotExitState = HotExitState.Allowed; + } } catch (e) { // Make sure state has not changed in the meantime if (this._hotExitState === pendingState) { From fac3bb4bf64afa342d15887ac4fcd1c3d526a270 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Thu, 27 Feb 2020 14:09:46 -0800 Subject: [PATCH 72/74] Clairify documentation docs Fixes #91514 --- src/vs/vscode.proposed.d.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/vs/vscode.proposed.d.ts b/src/vs/vscode.proposed.d.ts index 15474e3339a..d1ccd81b83f 100644 --- a/src/vs/vscode.proposed.d.ts +++ b/src/vs/vscode.proposed.d.ts @@ -1682,9 +1682,10 @@ declare module 'vscode' { * * The documentation is shown in the code actions menu if either: * - * - Code actions of `kind` are requested by VS Code. Note that in this case, we always pick the most specific - * documentation. For example, if documentation for both `Refactor` and `RefactorExtract` is provided, and we - * request code actions for `RefactorExtract`, we prefer the more specific documentation for `RefactorExtract`. + * - Code actions of `kind` are requested by VS Code. In this case, VS Code will show the documentation that + * most closely matches the requested code action kind. For example, if a provider has documentation for + * both `Refactor` and `RefactorExtract`, when the user requests code actions for `RefactorExtract`, + * VS Code will use the documentation for `RefactorExtract` intead of the documentation for `Refactor`. * * - Any code actions of `kind` are returned by the provider. */ From 1bbce1ce03d60c81d1247edfdf502d1aefe456db Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Thu, 27 Feb 2020 14:23:56 -0800 Subject: [PATCH 73/74] Improve docs for `CodeAction.disabled` For #85160 --- src/vs/vscode.d.ts | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/vs/vscode.d.ts b/src/vs/vscode.d.ts index cbf69745888..9e852eca701 100644 --- a/src/vs/vscode.d.ts +++ b/src/vs/vscode.d.ts @@ -2020,7 +2020,7 @@ declare module 'vscode' { * Base kind for source actions: `source` * * Source code actions apply to the entire file. They must be explicitly requested and will not show in the - * normal [light bulb](https://code.visualstudio.com/docs/editor/editingevolved#_code-action) menu. Source actions + * normal [lightbulb](https://code.visualstudio.com/docs/editor/editingevolved#_code-action) menu. Source actions * can be run on save using `editor.codeActionsOnSave` and are also shown in the `source` context menu. */ static readonly Source: CodeActionKind; @@ -2086,7 +2086,7 @@ declare module 'vscode' { /** * Requested kind of actions to return. * - * Actions not of this kind are filtered out before being shown by the lightbulb. + * Actions not of this kind are filtered out before being shown by the [lightbulb](https://code.visualstudio.com/docs/editor/editingevolved#_code-action). */ readonly only?: CodeActionKind; } @@ -2138,7 +2138,15 @@ declare module 'vscode' { /** * Marks that the code action cannot currently be applied. * - * Disabled code actions will be surfaced in the refactor UI but cannot be applied. + * - Disabled code actions are not shown in automatic [lightbulb](https://code.visualstudio.com/docs/editor/editingevolved#_code-action) + * code action menu. + * + * - Disabled actions are shown as faded out in the code action menu when the user request a more specific type + * of code action, such as refactorings. + * + * - If the user has a [keybinding](https://code.visualstudio.com/docs/editor/refactoring#_keybindings-for-code-actions) + * that auto applies a code action and only a disabled code actions are returned, VS Code will show the user a + * message with `reason` in the editor. */ disabled?: { /** @@ -2163,7 +2171,7 @@ declare module 'vscode' { /** * The code action interface defines the contract between extensions and - * the [light bulb](https://code.visualstudio.com/docs/editor/editingevolved#_code-action) feature. + * the [lightbulb](https://code.visualstudio.com/docs/editor/editingevolved#_code-action) feature. * * A code action can be any command that is [known](#commands.getCommands) to the system. */ From e5834d3280fcd04898efeac32b9cf1b893f9b127 Mon Sep 17 00:00:00 2001 From: Eric Amodio Date: Thu, 27 Feb 2020 17:31:32 -0500 Subject: [PATCH 74/74] Fixes #91378 --- src/vs/workbench/api/common/extHostTimeline.ts | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/vs/workbench/api/common/extHostTimeline.ts b/src/vs/workbench/api/common/extHostTimeline.ts index 87fefc82cfc..9db000d04f7 100644 --- a/src/vs/workbench/api/common/extHostTimeline.ts +++ b/src/vs/workbench/api/common/extHostTimeline.ts @@ -71,11 +71,17 @@ export class ExtHostTimeline implements IExtHostTimeline { scheme: scheme, onDidChange: undefined, async provideTimeline(uri: URI, options: TimelineOptions, token: CancellationToken, internalOptions?: { cacheResults?: boolean }) { - timelineDisposables.clear(); - // For now, only allow the caching of a single Uri - if (internalOptions?.cacheResults && !itemsBySourceByUriMap.has(getUriKey(uri))) { - itemsBySourceByUriMap.clear(); + if (internalOptions?.cacheResults) { + if (options.cursor === undefined) { + timelineDisposables.clear(); + } + + if (!itemsBySourceByUriMap.has(getUriKey(uri))) { + itemsBySourceByUriMap.clear(); + } + } else { + timelineDisposables.clear(); } const result = await provider.provideTimeline(uri, options, token);