Skip to content

Commit 8d14d4b

Browse files
committed
Add a Start Debugging Extension Host action in Runtime Extensions
1 parent f5658f0 commit 8d14d4b

8 files changed

Lines changed: 85 additions & 1 deletion

File tree

src/vs/workbench/parts/extensions/electron-browser/media/runtimeExtensionsEditor.css

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,14 @@
5353
padding: 10px 14px 10px 0;
5454
}
5555

56+
.monaco-action-bar .debug-extension-host {
57+
background: url('start.svg') center center no-repeat;
58+
}
59+
.vs-dark .monaco-action-bar .debug-extension-host,
60+
.hc-black .monaco-action-bar .debug-extension-host {
61+
background: url('start-inverse.svg') center center no-repeat;
62+
}
63+
5664
.monaco-action-bar .extension-host-profile-start {
5765
background: url('profile-start.svg') center center no-repeat;
5866
}
Lines changed: 1 addition & 0 deletions
Loading
Lines changed: 1 addition & 0 deletions
Loading

src/vs/workbench/parts/extensions/electron-browser/runtimeExtensionsEditor.ts

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ import { RunOnceScheduler } from 'vs/base/common/async';
2828
import { clipboard } from 'electron';
2929
import { LocalExtensionType } from 'vs/platform/extensionManagement/common/extensionManagement';
3030
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
31-
import { IWindowService } from 'vs/platform/windows/common/windows';
31+
import { IWindowService, IWindowsService } from 'vs/platform/windows/common/windows';
3232
import { writeFile } from 'vs/base/node/pfs';
3333
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
3434
import { memoize } from 'vs/base/common/decorators';
@@ -37,6 +37,9 @@ import { Event } from 'vs/base/common/event';
3737
import { DisableForWorkspaceAction, DisableGloballyAction } from 'vs/workbench/parts/extensions/electron-browser/extensionsActions';
3838
import { INotificationService } from 'vs/platform/notification/common/notification';
3939
import { RuntimeExtensionsInput } from 'vs/workbench/services/extensions/electron-browser/runtimeExtensionsInput';
40+
import { IDebugService } from 'vs/workbench/parts/debug/common/debug';
41+
import { IDialogService } from 'vs/platform/dialogs/common/dialogs';
42+
import { randomPort } from 'vs/base/node/ports';
4043

4144
export const IExtensionHostProfileService = createDecorator<IExtensionHostProfileService>('extensionHostProfileService');
4245

@@ -409,11 +412,17 @@ export class RuntimeExtensionsEditor extends BaseEditor {
409412

410413
public getActions(): IAction[] {
411414
return [
415+
this.debugExtensionHostAction,
412416
this.saveExtensionHostProfileAction,
413417
this.extensionHostProfileAction
414418
];
415419
}
416420

421+
@memoize
422+
private get debugExtensionHostAction(): IAction {
423+
return this._instantiationService.createInstance(DebugExtensionHostAction);
424+
}
425+
417426
@memoize
418427
private get extensionHostProfileAction(): IAction {
419428
return this._instantiationService.createInstance(ExtensionHostProfileAction, ExtensionHostProfileAction.ID, ExtensionHostProfileAction.LABEL_START);
@@ -484,6 +493,45 @@ class ReportExtensionIssueAction extends Action {
484493
}
485494
}
486495

496+
class DebugExtensionHostAction extends Action {
497+
static readonly ID = 'workbench.extensions.action.debugExtensionHost';
498+
static LABEL = nls.localize('debugExtensionHost', "Start Debugging Extension Host");
499+
static CSS_CLASS = 'debug-extension-host';
500+
501+
constructor(
502+
@IDebugService private readonly _debugService: IDebugService,
503+
@IWindowsService private readonly _windowsService: IWindowsService,
504+
@IDialogService private readonly _dialogService: IDialogService,
505+
@IExtensionService private readonly _extensionService: IExtensionService,
506+
) {
507+
super(DebugExtensionHostAction.ID, DebugExtensionHostAction.LABEL, DebugExtensionHostAction.CSS_CLASS);
508+
}
509+
510+
run(): TPromise<any> {
511+
512+
const inspectPort = this._extensionService.getInspectPort();
513+
if (!inspectPort) {
514+
return this._dialogService.confirm({
515+
type: 'info',
516+
message: nls.localize('restart1', "Profile Extensions"),
517+
detail: nls.localize('restart2', "In order to profile extensions a restart is required. Do you want to restart '{0}' now?", product.nameLong),
518+
primaryButton: nls.localize('restart3', "Restart"),
519+
secondaryButton: nls.localize('cancel', "Cancel")
520+
}).then(res => {
521+
if (res.confirmed) {
522+
this._windowsService.relaunch({ addArgs: [`--inspect-extensions=${randomPort()}`] });
523+
}
524+
});
525+
}
526+
527+
return this._debugService.startDebugging(null, {
528+
type: 'node',
529+
request: 'attach',
530+
port: inspectPort
531+
});
532+
}
533+
}
534+
487535
class ExtensionHostProfileAction extends Action {
488536
static readonly ID = 'workbench.extensions.action.extensionHostProfile';
489537
static LABEL_START = nls.localize('extensionHostProfileStart', "Start Extension Host Profile");

src/vs/workbench/services/commands/test/common/commandService.test.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,9 @@ class SimpleExtensionService implements IExtensionService {
4343
startExtensionHostProfile(): TPromise<ProfileSession> {
4444
throw new Error('Not implemented');
4545
}
46+
getInspectPort(): number {
47+
return 0;
48+
}
4649
restartExtensionHost(): void {
4750
}
4851
startExtensionHost(): void {

src/vs/workbench/services/extensions/common/extensions.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,11 @@ export interface IExtensionService {
173173
*/
174174
startExtensionHostProfile(): TPromise<ProfileSession>;
175175

176+
/**
177+
* Return the inspect port or 0.
178+
*/
179+
getInspectPort(): number;
180+
176181
/**
177182
* Restarts the extension host.
178183
*/

src/vs/workbench/services/extensions/electron-browser/extensionService.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,16 @@ export class ExtensionHostProcessManager extends Disposable {
248248
}
249249
throw new Error('Extension host not running or no inspect port available');
250250
}
251+
252+
public getInspectPort(): number {
253+
if (this._extensionHostProcessWorker) {
254+
let port = this._extensionHostProcessWorker.getInspectPort();
255+
if (port) {
256+
return port;
257+
}
258+
}
259+
return 0;
260+
}
251261
}
252262

253263
schema.properties.engines.properties.vscode.default = `^${pkg.version}`;
@@ -544,6 +554,13 @@ export class ExtensionService extends Disposable implements IExtensionService {
544554
throw new Error('Extension host not running or no inspect port available');
545555
}
546556

557+
public getInspectPort(): number {
558+
if (this._extensionHostProcessManagers.length > 0) {
559+
return this._extensionHostProcessManagers[0].getInspectPort();
560+
}
561+
return 0;
562+
}
563+
547564
// ---- end IExtensionService
548565

549566
// --- impl

src/vs/workbench/test/workbenchTestServices.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -310,6 +310,7 @@ export class TestExtensionService implements IExtensionService {
310310
readExtensionPointContributions<T>(extPoint: IExtensionPoint<T>): TPromise<ExtensionPointContribution<T>[]> { return TPromise.as(Object.create(null)); }
311311
getExtensionsStatus(): { [id: string]: IExtensionsStatus; } { return Object.create(null); }
312312
canProfileExtensionHost(): boolean { return false; }
313+
getInspectPort(): number { return 0; }
313314
startExtensionHostProfile(): TPromise<ProfileSession> { return TPromise.as(Object.create(null)); }
314315
restartExtensionHost(): void { }
315316
startExtensionHost(): void { }

0 commit comments

Comments
 (0)