diff --git a/package.json b/package.json index 576f643777271abe9001a46d1ef581b25189ea0a..299f9cd814d7033a26ab34469ebfe36c67ef2a2c 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "code-oss-dev", "version": "1.36.0", - "distro": "8a9f9dd1ba6499b20ee1f470a5c7b3fa1b684d7f", + "distro": "f582c39004c7c694d7e1461345e456afedd81d67", "author": { "name": "Microsoft Corporation" }, diff --git a/src/vs/base/common/lifecycle.ts b/src/vs/base/common/lifecycle.ts index 7d840b7bca4f201e298c83257087084f7684bebf..426f0ddeb8eafae389e5075faacc5b1d75b7f580 100644 --- a/src/vs/base/common/lifecycle.ts +++ b/src/vs/base/common/lifecycle.ts @@ -144,6 +144,52 @@ export abstract class Disposable implements IDisposable { } } +/** + * Manages the lifecycle of a disposable value that may be changed. + * + * This ensures that when the the disposable value is changed, the previously held disposable is disposed of. You can + * also register a `MutableDisposable` on a `Disposable` to ensure it is automatically cleaned up. + */ +export class MutableDisposable implements IDisposable { + private _value?: T; + private _isDisposed = false; + + constructor() { + trackDisposable(this); + } + + get value(): T | undefined { + return this._isDisposed ? undefined : this._value; + } + + set value(value: T | undefined) { + if (this._isDisposed || value === this._value) { + return; + } + + if (this._value) { + this._value.dispose(); + } + if (value) { + markTracked(value); + } + this._value = value; + } + + clear() { + this.value = undefined; + } + + dispose(): void { + this._isDisposed = true; + markTracked(this); + if (this._value) { + this._value.dispose(); + } + this._value = undefined; + } +} + export interface IReference extends IDisposable { readonly object: T; } diff --git a/src/vs/code/browser/workbench/workbench.html b/src/vs/code/browser/workbench/workbench.html index 07ac3c653dfa63676f6ae7715f24c732cd8695a3..30598e4a5661501585dbecaa93c6191dd69c520a 100644 --- a/src/vs/code/browser/workbench/workbench.html +++ b/src/vs/code/browser/workbench/workbench.html @@ -16,6 +16,7 @@ self.SERVER_APP_ROOT = '{{SERVER_APP_ROOT}}'; self.WINDOW_CONFIGURATION = { settingsPath: '{{SETTINGS}}', + keybindingsPath: '{{KEYBINDINGS}}', folderPath: '{{FOLDER}}', workspacePath: '{{WORKSPACE}}', } diff --git a/src/vs/editor/contrib/codeAction/codeActionModel.ts b/src/vs/editor/contrib/codeAction/codeActionModel.ts index a730090bdd1f798ed38587ec0ab61bca1cae0f9a..8b6cc5a48632bb8270b2346f65fbb2140a0cd074 100644 --- a/src/vs/editor/contrib/codeAction/codeActionModel.ts +++ b/src/vs/editor/contrib/codeAction/codeActionModel.ts @@ -5,7 +5,7 @@ import { CancelablePromise, createCancelablePromise, TimeoutTimer } from 'vs/base/common/async'; import { Emitter } from 'vs/base/common/event'; -import { dispose, Disposable } from 'vs/base/common/lifecycle'; +import { Disposable, MutableDisposable } from 'vs/base/common/lifecycle'; import { URI } from 'vs/base/common/uri'; import { ICodeEditor } from 'vs/editor/browser/editorBrowser'; import { Position } from 'vs/editor/common/core/position'; @@ -156,7 +156,7 @@ export namespace CodeActionsState { export class CodeActionModel extends Disposable { - private _codeActionOracle?: CodeActionOracle; + private readonly _codeActionOracle = this._register(new MutableDisposable()); private _state: CodeActionsState.State = CodeActionsState.Empty; private readonly _supportedCodeActions: IContextKey; @@ -181,15 +181,11 @@ export class CodeActionModel extends Disposable { dispose(): void { super.dispose(); - dispose(this._codeActionOracle); this.setState(CodeActionsState.Empty, true); } private _update(): void { - if (this._codeActionOracle) { - this._codeActionOracle.dispose(); - this._codeActionOracle = undefined; - } + this._codeActionOracle.value = undefined; this.setState(CodeActionsState.Empty); @@ -207,7 +203,7 @@ export class CodeActionModel extends Disposable { this._supportedCodeActions.set(supportedActions.join(' ')); - this._codeActionOracle = new CodeActionOracle(this._editor, this._markerService, trigger => { + this._codeActionOracle.value = new CodeActionOracle(this._editor, this._markerService, trigger => { if (!trigger) { this.setState(CodeActionsState.Empty); return; @@ -221,15 +217,15 @@ export class CodeActionModel extends Disposable { this.setState(new CodeActionsState.Triggered(trigger.trigger, trigger.selection, trigger.position, actions)); }, undefined); - this._codeActionOracle.trigger({ type: 'auto' }); + this._codeActionOracle.value.trigger({ type: 'auto' }); } else { this._supportedCodeActions.reset(); } } public trigger(trigger: CodeActionTrigger) { - if (this._codeActionOracle) { - this._codeActionOracle.trigger(trigger); + if (this._codeActionOracle.value) { + this._codeActionOracle.value.trigger(trigger); } } diff --git a/src/vs/platform/actions/browser/menuEntryActionViewItem.ts b/src/vs/platform/actions/browser/menuEntryActionViewItem.ts index d6c83d65768bb8aac591f7a51d0e3aa074160d6a..331fa1156f1bd472ba0f0027fea79a3c9cbc8eb8 100644 --- a/src/vs/platform/actions/browser/menuEntryActionViewItem.ts +++ b/src/vs/platform/actions/browser/menuEntryActionViewItem.ts @@ -9,7 +9,7 @@ import { ActionViewItem, Separator } from 'vs/base/browser/ui/actionbar/actionba import { IAction } from 'vs/base/common/actions'; import { Emitter } from 'vs/base/common/event'; import { IdGenerator } from 'vs/base/common/idGenerator'; -import { dispose, IDisposable, toDisposable } from 'vs/base/common/lifecycle'; +import { dispose, IDisposable, toDisposable, MutableDisposable } from 'vs/base/common/lifecycle'; import { isLinux, isWindows } from 'vs/base/common/platform'; import { localize } from 'vs/nls'; import { ICommandAction, IMenu, IMenuActionOptions, MenuItemAction, SubmenuItemAction } from 'vs/platform/actions/common/actions'; @@ -127,7 +127,7 @@ export class MenuEntryActionViewItem extends ActionViewItem { static readonly ICON_PATH_TO_CSS_RULES: Map = new Map(); private _wantsAltCommand: boolean; - private _itemClassDispose?: IDisposable; + private readonly _itemClassDispose = this._register(new MutableDisposable()); private readonly _altKey: AlternativeKeyEmitter; constructor( @@ -222,8 +222,7 @@ export class MenuEntryActionViewItem extends ActionViewItem { } _updateItemClass(item: ICommandAction): void { - dispose(this._itemClassDispose); - this._itemClassDispose = undefined; + this._itemClassDispose.value = undefined; if (item.iconLocation) { let iconClass: string; @@ -240,18 +239,9 @@ export class MenuEntryActionViewItem extends ActionViewItem { } addClasses(this.label, 'icon', iconClass); - this._itemClassDispose = toDisposable(() => removeClasses(this.label, 'icon', iconClass)); + this._itemClassDispose.value = toDisposable(() => removeClasses(this.label, 'icon', iconClass)); } } - - dispose(): void { - if (this._itemClassDispose) { - dispose(this._itemClassDispose); - this._itemClassDispose = undefined; - } - - super.dispose(); - } } // Need to subclass MenuEntryActionViewItem in order to respect diff --git a/src/vs/vscode.d.ts b/src/vs/vscode.d.ts index f5be21364a09fa80478ab7750cb220cb16e0fb3d..498d0761462bf74c456d885ac7aa814ca2057b2d 100644 --- a/src/vs/vscode.d.ts +++ b/src/vs/vscode.d.ts @@ -9102,7 +9102,7 @@ declare module 'vscode' { * Context value of the comment. This can be used to contribute comment specific actions. * For example, a comment is given a context value as `editable`. When contributing actions to `comments/comment/title` * using `menus` extension point, you can specify context value for key `comment` in `when` expression like `comment == editable`. - * ``` + * ```json * "contributes": { * "menus": { * "comments/comment/title": [ diff --git a/src/vs/workbench/browser/media/icons.css b/src/vs/workbench/browser/media/icons.css index 8fe2c5ad35e4cf34b2c64e1eb445883aa959d7aa..34d60749173dee23203aba88c9b20a4928ebcdd5 100644 --- a/src/vs/workbench/browser/media/icons.css +++ b/src/vs/workbench/browser/media/icons.css @@ -1229,4 +1229,9 @@ body[data-exploration="icon-exploration"] .monaco-editor .margin-view-overlays . body[data-exploration="icon-exploration"] .monaco-editor .margin-view-overlays .folding.collapsed { -webkit-mask-image: url("images/misc/unfold-alt1.svg"); +} + +body[data-exploration="icon-exploration"] .monaco-editor .find-widget .matchesCount { + margin-right: 0; + padding-right: 0; } \ No newline at end of file diff --git a/src/vs/workbench/browser/web.main.ts b/src/vs/workbench/browser/web.main.ts index 3b1d5040479ea8583c52ee854d4908c74254a331..0264fc6cadd1b21608abeb1f959f7307a7c17ac2 100644 --- a/src/vs/workbench/browser/web.main.ts +++ b/src/vs/workbench/browser/web.main.ts @@ -36,6 +36,7 @@ import { hash } from 'vs/base/common/hash'; interface IWindowConfiguration { settingsUri: URI; + keybindingsUri: URI; remoteAuthority: string; folderUri?: URI; workspaceUri?: URI; @@ -141,7 +142,7 @@ class CodeRendererMain extends Disposable { environmentService.args = { _: [] }; environmentService.appSettingsHome = toResource('/web/settings'); environmentService.settingsResource = this.configuration.settingsUri; - environmentService.keybindingsResource = toResource('/web/settings/keybindings.json'); + environmentService.keybindingsResource = this.configuration.keybindingsUri; environmentService.logsPath = '/web/logs'; environmentService.debugExtensionHost = { port: null, @@ -184,6 +185,7 @@ class CodeRendererMain extends Disposable { export interface IWindowConfigurationContents { settingsPath: string; + keybindingsPath: string; folderPath?: string; workspacePath?: string; } @@ -191,6 +193,7 @@ export interface IWindowConfigurationContents { export function main(windowConfigurationContents: IWindowConfigurationContents): Promise { const windowConfiguration: IWindowConfiguration = { settingsUri: toResource(windowConfigurationContents.settingsPath), + keybindingsUri: toResource(windowConfigurationContents.keybindingsPath), folderUri: windowConfigurationContents.folderPath ? toResource(windowConfigurationContents.folderPath) : undefined, workspaceUri: windowConfigurationContents.workspacePath ? toResource(windowConfigurationContents.workspacePath) : undefined, remoteAuthority: document.location.host diff --git a/src/vs/workbench/contrib/extensions/electron-browser/extensions.contribution.ts b/src/vs/workbench/contrib/extensions/electron-browser/extensions.contribution.ts index 91cfd75655e2681c2e80eb02b82e22befe76a3ed..2fd792e067efa1e6d2d5fd51c472d51427d62981 100644 --- a/src/vs/workbench/contrib/extensions/electron-browser/extensions.contribution.ts +++ b/src/vs/workbench/contrib/extensions/electron-browser/extensions.contribution.ts @@ -307,7 +307,7 @@ MenuRegistry.appendMenuItem(MenuId.MenubarPreferencesMenu, { id: VIEWLET_ID, title: localize({ key: 'miPreferencesExtensions', comment: ['&& denotes a mnemonic'] }, "&&Extensions") }, - order: 2 + order: 3 }); // View menu diff --git a/src/vs/workbench/contrib/outline/browser/outlinePanel.ts b/src/vs/workbench/contrib/outline/browser/outlinePanel.ts index c2670678d6b3af7e85824d1a7a673e7396f1f378..b83ce3375434801725a4632354b4a785a480c837 100644 --- a/src/vs/workbench/contrib/outline/browser/outlinePanel.ts +++ b/src/vs/workbench/contrib/outline/browser/outlinePanel.ts @@ -11,7 +11,7 @@ import { createCancelablePromise, TimeoutTimer } from 'vs/base/common/async'; import { isPromiseCanceledError } from 'vs/base/common/errors'; import { Emitter } from 'vs/base/common/event'; import { defaultGenerator } from 'vs/base/common/idGenerator'; -import { dispose, IDisposable, toDisposable } from 'vs/base/common/lifecycle'; +import { dispose, IDisposable, toDisposable, DisposableStore } from 'vs/base/common/lifecycle'; import { LRUCache } from 'vs/base/common/map'; import { escape } from 'vs/base/common/strings'; import 'vs/css!./outlinePanel'; @@ -70,7 +70,7 @@ class RequestState { class RequestOracle { - private _disposables = new Array(); + private readonly _disposables = new DisposableStore(); private _sessionDisposable: IDisposable; private _lastState?: RequestState; diff --git a/src/vs/workbench/contrib/preferences/browser/preferences.contribution.ts b/src/vs/workbench/contrib/preferences/browser/preferences.contribution.ts index 7015ee8f1e8d6f268ec024eaac55341c5fe4525d..56cdd4a67905431a73589f31ac5bc90ee51c6de3 100644 --- a/src/vs/workbench/contrib/preferences/browser/preferences.contribution.ts +++ b/src/vs/workbench/contrib/preferences/browser/preferences.contribution.ts @@ -741,6 +741,8 @@ CommandsRegistry.registerCommand(SETTINGS_EDITOR_COMMAND_FILTER_ONLINE, serviceA const control = serviceAccessor.get(IEditorService).activeControl as SettingsEditor2; if (control instanceof SettingsEditor2) { control.focusSearch(`@tag:usesOnlineServices`); + } else { + serviceAccessor.get(IPreferencesService).openSettings(undefined, '@tag:usesOnlineServices'); } }); @@ -764,6 +766,15 @@ MenuRegistry.appendMenuItem(MenuId.GlobalActivity, { order: 1 }); +MenuRegistry.appendMenuItem(MenuId.MenubarPreferencesMenu, { + group: '1_settings', + command: { + id: SETTINGS_EDITOR_COMMAND_FILTER_ONLINE, + title: nls.localize({ key: 'miOpenOnlineSettings', comment: ['&& denotes a mnemonic'] }, "&&Online Services Settings") + }, + order: 2 +}); + MenuRegistry.appendMenuItem(MenuId.MenubarPreferencesMenu, { group: '2_keybindings', command: { diff --git a/src/vs/workbench/contrib/snippets/browser/tabCompletion.ts b/src/vs/workbench/contrib/snippets/browser/tabCompletion.ts index 33f6bedb3305a25f19de531c28e795489e042a4b..15c2ebd44d9251aaa604f615dd03e63b4851c25b 100644 --- a/src/vs/workbench/contrib/snippets/browser/tabCompletion.ts +++ b/src/vs/workbench/contrib/snippets/browser/tabCompletion.ts @@ -33,7 +33,7 @@ export class TabCompletionController implements editorCommon.IEditorContribution private _activeSnippets: Snippet[] = []; private _enabled: boolean; private _selectionListener: IDisposable; - private _configListener: IDisposable; + private readonly _configListener: IDisposable; constructor( private readonly _editor: ICodeEditor, diff --git a/src/vs/workbench/contrib/webview/browser/webviewEditor.ts b/src/vs/workbench/contrib/webview/browser/webviewEditor.ts index 45493bed5be05bf50fda423038d8794b47354379..7c5730e4457b6ea55a284b6dd85e4f18263ab848 100644 --- a/src/vs/workbench/contrib/webview/browser/webviewEditor.ts +++ b/src/vs/workbench/contrib/webview/browser/webviewEditor.ts @@ -6,7 +6,7 @@ import * as DOM from 'vs/base/browser/dom'; import { CancellationToken } from 'vs/base/common/cancellation'; import { Emitter, Event } from 'vs/base/common/event'; -import { IDisposable, DisposableStore } from 'vs/base/common/lifecycle'; +import { DisposableStore, MutableDisposable } from 'vs/base/common/lifecycle'; import { URI } from 'vs/base/common/uri'; import { IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; import { IStorageService } from 'vs/platform/storage/common/storage'; @@ -33,8 +33,8 @@ export class WebviewEditor extends BaseEditor { private _content?: HTMLElement; private _webviewContent: HTMLElement | undefined; - private readonly _webviewFocusTrackerDisposables = new DisposableStore(); - private _onFocusWindowHandler?: IDisposable; + private readonly _webviewFocusTrackerDisposables = this._register(new DisposableStore()); + private readonly _onFocusWindowHandler = this._register(new MutableDisposable()); private readonly _onDidFocusWebview = this._register(new Emitter()); public get onDidFocus(): Event { return this._onDidFocusWebview.event; } @@ -89,12 +89,6 @@ export class WebviewEditor extends BaseEditor { this._content = undefined; } - this._webviewFocusTrackerDisposables.dispose(); - - if (this._onFocusWindowHandler) { - this._onFocusWindowHandler.dispose(); - } - super.dispose(); } @@ -136,10 +130,10 @@ export class WebviewEditor extends BaseEditor { public focus(): void { super.focus(); - if (!this._onFocusWindowHandler) { + if (!this._onFocusWindowHandler.value) { // Make sure we restore focus when switching back to a VS Code window - this._onFocusWindowHandler = this._windowService.onDidChangeFocus(focused => { + this._onFocusWindowHandler.value = this._windowService.onDidChangeFocus(focused => { if (focused && this._editorService.activeControl === this) { this.focus(); } diff --git a/src/vs/workbench/services/progress/browser/progressService.ts b/src/vs/workbench/services/progress/browser/progressService.ts index df47de29be33739260d5ce279fabaa140916a7ed..a5dbd5190e2e02ca0aaa05a4499a45bef241a6cc 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 } from 'vs/base/common/lifecycle'; +import { IDisposable, dispose, DisposableStore, MutableDisposable } from 'vs/base/common/lifecycle'; import { IProgressService, IProgressOptions, IProgressStep, ProgressLocation, IProgress, emptyProgress, Progress, IProgressCompositeOptions, IProgressNotificationOptions } from 'vs/platform/progress/common/progress'; import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet'; import { StatusbarAlignment, IStatusbarService } from 'vs/platform/statusbar/common/statusbar'; @@ -25,12 +25,12 @@ import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent'; import { EventHelper } from 'vs/base/browser/dom'; import { ServiceIdentifier } from 'vs/platform/instantiation/common/instantiation'; -export class ProgressService implements IProgressService { +export class ProgressService implements IProgressService, IDisposable { _serviceBrand: ServiceIdentifier; private readonly _stack: [IProgressOptions, Progress][] = []; - private _globalStatusEntry: IDisposable; + private readonly _globalStatusEntry = new MutableDisposable(); constructor( @IActivityService private readonly _activityBar: IActivityService, @@ -42,6 +42,10 @@ export class ProgressService implements IProgressService { @IKeybindingService private readonly _keybindingService: IKeybindingService ) { } + dispose() { + this._globalStatusEntry.dispose(); + } + withProgress(options: IProgressOptions, task: (progress: IProgress) => Promise, onDidCancel?: () => void): Promise { const { location } = options; if (typeof location === 'string') { @@ -97,7 +101,7 @@ export class ProgressService implements IProgressService { } private _updateWindowProgress(idx: number = 0) { - dispose(this._globalStatusEntry); + this._globalStatusEntry.clear(); if (idx < this._stack.length) { const [options, progress] = this._stack[idx]; @@ -128,7 +132,7 @@ export class ProgressService implements IProgressService { return; } - this._globalStatusEntry = this._statusbarService.addEntry({ + this._globalStatusEntry.value = this._statusbarService.addEntry({ text: `$(sync~spin) ${text}`, tooltip: title }, 'status.progress', localize('status.progress', "Progress Message"), StatusbarAlignment.LEFT);