From ca35e2c8d72bc5316da12ceeb31c966ddeff1ad0 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Mon, 3 Jun 2019 11:15:39 +0200 Subject: [PATCH] debt - convert profile status to status item --- .../extensionProfileService.ts | 137 +++++++----------- .../media/runtimeExtensionsEditor.css | 17 --- 2 files changed, 51 insertions(+), 103 deletions(-) diff --git a/src/vs/workbench/contrib/extensions/electron-browser/extensionProfileService.ts b/src/vs/workbench/contrib/extensions/electron-browser/extensionProfileService.ts index c4bcd08d1e8..53badb9e040 100644 --- a/src/vs/workbench/contrib/extensions/electron-browser/extensionProfileService.ts +++ b/src/vs/workbench/contrib/extensions/electron-browser/extensionProfileService.ts @@ -5,14 +5,11 @@ import * as nls from 'vs/nls'; import { Event, Emitter } from 'vs/base/common/event'; -import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; +import { IInstantiationService, ServiceIdentifier } from 'vs/platform/instantiation/common/instantiation'; import { IExtensionHostProfile, ProfileSession, IExtensionService } from 'vs/workbench/services/extensions/common/extensions'; -import { Disposable, IDisposable, dispose } from 'vs/base/common/lifecycle'; +import { Disposable, IDisposable, toDisposable } from 'vs/base/common/lifecycle'; import { onUnexpectedError } from 'vs/base/common/errors'; -import { append, $, addDisposableListener } from 'vs/base/browser/dom'; -import { IStatusbarRegistry, StatusbarItemDescriptor, Extensions, IStatusbarItem } from 'vs/workbench/browser/parts/statusbar/statusbar'; -import { StatusbarAlignment } from 'vs/platform/statusbar/common/statusbar'; -import { Registry } from 'vs/platform/registry/common/platform'; +import { StatusbarAlignment, IStatusbarService, IStatusbarEntryAccessor, IStatusbarEntry } from 'vs/platform/statusbar/common/statusbar'; import { IExtensionHostProfileService, ProfileSessionState } from 'vs/workbench/contrib/extensions/electron-browser/runtimeExtensionsEditor'; import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; import { IWindowsService } from 'vs/platform/windows/common/windows'; @@ -22,10 +19,11 @@ import product from 'vs/platform/product/node/product'; import { RuntimeExtensionsInput } from 'vs/workbench/contrib/extensions/electron-browser/runtimeExtensionsInput'; import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions'; import { ExtensionHostProfiler } from 'vs/workbench/services/extensions/electron-browser/extensionHostProfiler'; +import { CommandsRegistry } from 'vs/platform/commands/common/commands'; export class ExtensionHostProfileService extends Disposable implements IExtensionHostProfileService { - _serviceBrand: any; + _serviceBrand: ServiceIdentifier; private readonly _onDidChangeState: Emitter = this._register(new Emitter()); public readonly onDidChangeState: Event = this._onDidChangeState.event; @@ -38,6 +36,9 @@ export class ExtensionHostProfileService extends Disposable implements IExtensio private _profileSession: ProfileSession | null; private _state: ProfileSessionState; + private profilingStatusBarIndicator: IStatusbarEntryAccessor | undefined; + private profilingStatusBarIndicatorLabelUpdater: IDisposable | undefined; + public get state() { return this._state; } public get lastProfile() { return this._profile; } @@ -46,12 +47,18 @@ export class ExtensionHostProfileService extends Disposable implements IExtensio @IEditorService private readonly _editorService: IEditorService, @IInstantiationService private readonly _instantiationService: IInstantiationService, @IWindowsService private readonly _windowsService: IWindowsService, - @IDialogService private readonly _dialogService: IDialogService + @IDialogService private readonly _dialogService: IDialogService, + @IStatusbarService private readonly _statusbarService: IStatusbarService, ) { super(); this._profile = null; this._profileSession = null; this._setState(ProfileSessionState.None); + + CommandsRegistry.registerCommand('workbench.action.extensionHostProfilder.stop', () => { + this.stopProfiling(); + this._editorService.openEditor(this._instantiationService.createInstance(RuntimeExtensionsInput), { revealIfOpened: true }); + }); } private _setState(state: ProfileSessionState): void { @@ -61,17 +68,48 @@ export class ExtensionHostProfileService extends Disposable implements IExtensio this._state = state; if (this._state === ProfileSessionState.Running) { - ProfileExtHostStatusbarItem.instance.show(() => { - this.stopProfiling(); - this._editorService.openEditor(this._instantiationService.createInstance(RuntimeExtensionsInput), { revealIfOpened: true }); - }); + this.updateProfilingStatusBarIndicator(true); } else if (this._state === ProfileSessionState.Stopping) { - ProfileExtHostStatusbarItem.instance.hide(); + this.updateProfilingStatusBarIndicator(false); } this._onDidChangeState.fire(undefined); } + private updateProfilingStatusBarIndicator(visible: boolean): void { + if (this.profilingStatusBarIndicatorLabelUpdater) { + this.profilingStatusBarIndicatorLabelUpdater.dispose(); + this.profilingStatusBarIndicatorLabelUpdater = undefined; + } + + if (visible) { + const indicator: IStatusbarEntry = { + text: nls.localize('profilingExtensionHost', "$(sync~spin) Profiling Extension Host"), + tooltip: nls.localize('selectAndStartDebug', "Click to stop profiling."), + command: 'workbench.action.extensionHostProfilder.stop' + }; + + const timeStarted = Date.now(); + const handle = setInterval(() => { + if (this.profilingStatusBarIndicator) { + this.profilingStatusBarIndicator.update({ ...indicator, text: nls.localize('profilingExtensionHostTime', "$(sync~spin) Profiling Extension Host ({0} sec)", Math.round((new Date().getTime() - timeStarted) / 1000)), }); + } + }, 1000); + this.profilingStatusBarIndicatorLabelUpdater = toDisposable(() => clearInterval(handle)); + + if (!this.profilingStatusBarIndicator) { + this.profilingStatusBarIndicator = this._statusbarService.addEntry(indicator, StatusbarAlignment.RIGHT); + } else { + this.profilingStatusBarIndicator.update(indicator); + } + } else { + if (this.profilingStatusBarIndicator) { + this.profilingStatusBarIndicator.dispose(); + this.profilingStatusBarIndicator = undefined; + } + } + } + public startProfiling(): Promise | null { if (this._state !== ProfileSessionState.None) { return null; @@ -134,76 +172,3 @@ export class ExtensionHostProfileService extends Disposable implements IExtensio } } - -export class ProfileExtHostStatusbarItem implements IStatusbarItem { - - public static instance: ProfileExtHostStatusbarItem; - - private toDispose: IDisposable[]; - private statusBarItem: HTMLElement; - private label: HTMLElement; - private timeStarted: number; - private labelUpdater: any; - private clickHandler: (() => void) | null; - - constructor() { - ProfileExtHostStatusbarItem.instance = this; - this.toDispose = []; - this.timeStarted = 0; - } - - public show(clickHandler: () => void) { - this.clickHandler = clickHandler; - if (this.timeStarted === 0) { - this.timeStarted = new Date().getTime(); - this.statusBarItem.hidden = false; - this.labelUpdater = setInterval(() => { - this.updateLabel(); - }, 1000); - this.updateLabel(); - } - } - - public hide() { - this.clickHandler = null; - this.statusBarItem.hidden = true; - this.timeStarted = 0; - clearInterval(this.labelUpdater); - this.labelUpdater = null; - } - - public render(container: HTMLElement): IDisposable { - if (!this.statusBarItem && container) { - this.statusBarItem = append(container, $('.profileExtHost-statusbar-item')); - this.toDispose.push(addDisposableListener(this.statusBarItem, 'click', () => { - if (this.clickHandler) { - this.clickHandler(); - } - })); - this.statusBarItem.title = nls.localize('selectAndStartDebug', "Click to stop profiling."); - const a = append(this.statusBarItem, $('a')); - append(a, $('.icon')); - this.label = append(a, $('span.label')); - this.updateLabel(); - this.statusBarItem.hidden = true; - } - return this; - } - - private updateLabel() { - let label = 'Profiling Extension Host'; - if (this.timeStarted > 0) { - let secondsRecoreded = (new Date().getTime() - this.timeStarted) / 1000; - label = `Profiling Extension Host (${Math.round(secondsRecoreded)} sec)`; - } - this.label.textContent = label; - } - - public dispose(): void { - this.toDispose = dispose(this.toDispose); - } -} - -Registry.as(Extensions.Statusbar).registerStatusbarItem( - new StatusbarItemDescriptor(ProfileExtHostStatusbarItem, StatusbarAlignment.RIGHT) -); diff --git a/src/vs/workbench/contrib/extensions/electron-browser/media/runtimeExtensionsEditor.css b/src/vs/workbench/contrib/extensions/electron-browser/media/runtimeExtensionsEditor.css index a63beff915d..cedd8541829 100644 --- a/src/vs/workbench/contrib/extensions/electron-browser/media/runtimeExtensionsEditor.css +++ b/src/vs/workbench/contrib/extensions/electron-browser/media/runtimeExtensionsEditor.css @@ -36,20 +36,3 @@ .runtime-extensions-editor .monaco-action-bar .actions-container { justify-content: left; } - -.monaco-workbench .part.statusbar .profileExtHost-statusbar-item .icon { - background: url('profile-stop.svg') no-repeat; - display: inline-block; - padding-right: 2px; - padding-bottom: 2px; - width: 16px; - height: 16px; - vertical-align: middle; - animation:fade 1000ms infinite; -} - -@keyframes fade { - from { opacity: 1.0; } - 50% { opacity: 0.5; } - to { opacity: 1.0; } -}