Skip to content

Commit b2fcf2d

Browse files
committed
1 parent 17f0e4b commit b2fcf2d

5 files changed

Lines changed: 137 additions & 20 deletions

File tree

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
/*---------------------------------------------------------------------------------------------
2+
* Copyright (c) Microsoft Corporation. All rights reserved.
3+
* Licensed under the MIT License. See License.txt in the project root for license information.
4+
*--------------------------------------------------------------------------------------------*/
5+
6+
import { BrandedService, IInstantiationService, ServicesAccessor, IConstructorSignature0 } from 'vs/platform/instantiation/common/instantiation';
7+
import { Registry } from 'vs/platform/registry/common/platform';
8+
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
9+
10+
/**
11+
* An ext host contribution that will be loaded when the extension host starts and disposed when the extension host shuts down.
12+
*/
13+
export interface IExtHostContribution extends IDisposable {
14+
// Marker Interface
15+
}
16+
17+
export namespace Extensions {
18+
export const ExtHost = 'exthost.contributions.kind';
19+
}
20+
21+
type IExtHostContributionSignature<Service extends BrandedService[]> = new (...services: Service) => IExtHostContribution;
22+
23+
export interface IExtHostContributionsRegistry {
24+
25+
/**
26+
* Registers a ext host contribution to the platform that will be loaded when the extension host starts and disposed when the extension host shuts down.
27+
*/
28+
registerExtHostContribution<Services extends BrandedService[]>(contribution: IExtHostContributionSignature<Services>): void;
29+
30+
/**
31+
* Starts the registry by providing the required services.
32+
*/
33+
start(accessor: ServicesAccessor): void;
34+
35+
/**
36+
* Stops the registry by disposing the instantiated contributions
37+
*/
38+
stop(): void;
39+
}
40+
41+
class ExtHostContributionsRegistry implements IExtHostContributionsRegistry {
42+
43+
private instantiationService: IInstantiationService | undefined;
44+
private readonly contributions: IConstructorSignature0<IExtHostContribution>[] = [];
45+
private toBeInstantiated: IConstructorSignature0<IExtHostContribution>[] = [];
46+
private instantiated: IExtHostContribution[] = [];
47+
48+
registerExtHostContribution<Services extends BrandedService[]>(ctor: { new(...services: Services): IExtHostContribution }): void {
49+
this.contributions.push(ctor);
50+
51+
// Instantiate directly if started
52+
if (this.instantiationService) {
53+
this.instantiate(ctor);
54+
}
55+
56+
// Otherwise keep contributions to be instantiated
57+
else {
58+
this.toBeInstantiated.push(ctor);
59+
}
60+
}
61+
62+
start(accessor: ServicesAccessor): void {
63+
this.instantiationService = accessor.get(IInstantiationService);
64+
this.toBeInstantiated.forEach(ctor => this.instantiate(ctor), this);
65+
this.toBeInstantiated = [];
66+
}
67+
68+
private instantiate<Services extends BrandedService[]>(ctor: { new(...services: Services): IExtHostContribution }) {
69+
this.instantiated.push(this.instantiationService!.createInstance(ctor));
70+
}
71+
72+
stop(): void {
73+
this.instantiationService = undefined;
74+
this.instantiated.forEach(dispose);
75+
this.instantiated = [];
76+
this.toBeInstantiated = [...this.contributions];
77+
}
78+
79+
}
80+
81+
Registry.add(Extensions.ExtHost, new ExtHostContributionsRegistry());
82+

src/vs/workbench/api/common/extHostInitDataService.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,12 @@
55

66
import { IInitData } from './extHost.protocol';
77
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
8+
import { URI } from 'vs/base/common/uri';
89

910
export const IExtHostInitDataService = createDecorator<IExtHostInitDataService>('IExtHostInitDataService');
1011

1112
export interface IExtHostInitDataService extends Readonly<IInitData> {
1213
_serviceBrand: undefined;
14+
readonly logFile: URI;
1315
}
1416

src/vs/workbench/api/node/extHostLogService.ts

Lines changed: 23 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,34 +3,45 @@
33
* Licensed under the MIT License. See License.txt in the project root for license information.
44
*--------------------------------------------------------------------------------------------*/
55

6-
import { localize } from 'vs/nls';
7-
import { join } from 'vs/base/common/path';
86
import { ILogService, DelegatedLogService, LogLevel } from 'vs/platform/log/common/log';
97
import { ExtHostLogServiceShape } from 'vs/workbench/api/common/extHost.protocol';
108
import { ExtensionHostLogFileName } from 'vs/workbench/services/extensions/common/extensions';
11-
import { URI } from 'vs/base/common/uri';
129
import { IExtHostInitDataService } from 'vs/workbench/api/common/extHostInitDataService';
1310
import { Schemas } from 'vs/base/common/network';
1411
import { SpdLogService } from 'vs/platform/log/node/spdlogService';
12+
import { dirname } from 'vs/base/common/resources';
13+
import { IExtHostContribution, IExtHostContributionsRegistry, Extensions } from 'vs/workbench/api/common/extHostContributions';
1514
import { IExtHostOutputService } from 'vs/workbench/api/common/extHostOutput';
15+
import { localize } from 'vs/nls';
16+
import { Registry } from 'vs/platform/registry/common/platform';
17+
import { Disposable } from 'vs/base/common/lifecycle';
1618

1719
export class ExtHostLogService extends DelegatedLogService implements ILogService, ExtHostLogServiceShape {
1820

1921
constructor(
2022
@IExtHostInitDataService initData: IExtHostInitDataService,
21-
@IExtHostOutputService extHostOutputService: IExtHostOutputService
2223
) {
23-
if (initData.logsLocation.scheme !== Schemas.file) { throw new Error('Only file-logging supported'); }
24-
super(new SpdLogService(ExtensionHostLogFileName, initData.logsLocation.fsPath, initData.logLevel));
25-
26-
// Register an output channel for exthost log
27-
extHostOutputService.createOutputChannelFromLogFile(
28-
initData.remote.isRemote ? localize('remote extension host Log', "Remote Extension Host") : localize('extension host Log', "Extension Host"),
29-
URI.file(join(initData.logsLocation.fsPath, `${ExtensionHostLogFileName}.log`))
30-
);
24+
if (initData.logFile.scheme !== Schemas.file) { throw new Error('Only file-logging supported'); }
25+
super(new SpdLogService(ExtensionHostLogFileName, dirname(initData.logFile).fsPath, initData.logLevel));
3126
}
3227

3328
$setLevel(level: LogLevel): void {
3429
this.setLevel(level);
3530
}
3631
}
32+
33+
class ExtHostLogChannelContribution extends Disposable implements IExtHostContribution {
34+
35+
constructor(
36+
@IExtHostInitDataService initData: IExtHostInitDataService,
37+
@IExtHostOutputService outputSerice: IExtHostOutputService,
38+
) {
39+
super();
40+
outputSerice.createOutputChannelFromLogFile(
41+
initData.remote.isRemote ? localize('remote extension host Log', "Remote Extension Host") : localize('extension host Log', "Extension Host"),
42+
initData.logFile);
43+
}
44+
45+
}
46+
47+
Registry.as<IExtHostContributionsRegistry>(Extensions.ExtHost).registerExtHostContribution(ExtHostLogChannelContribution);

src/vs/workbench/api/worker/extHostLogService.ts

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,11 @@ import { ExtHostLogServiceShape, MainThreadLogShape, MainContext } from 'vs/work
88
import { IExtHostInitDataService } from 'vs/workbench/api/common/extHostInitDataService';
99
import { IExtHostOutputService } from 'vs/workbench/api/common/extHostOutput';
1010
import { IExtHostRpcService } from 'vs/workbench/api/common/extHostRpcService';
11-
import { joinPath } from 'vs/base/common/resources';
12-
import { ExtensionHostLogFileName } from 'vs/workbench/services/extensions/common/extensions';
1311
import { UriComponents } from 'vs/base/common/uri';
1412
import { localize } from 'vs/nls';
13+
import { IExtHostContribution, IExtHostContributionsRegistry, Extensions } from 'vs/workbench/api/common/extHostContributions';
14+
import { Registry } from 'vs/platform/registry/common/platform';
15+
import { Disposable } from 'vs/base/common/lifecycle';
1516

1617
export class ExtHostLogService extends AbstractLogService implements ILogService, ExtHostLogServiceShape {
1718

@@ -23,14 +24,11 @@ export class ExtHostLogService extends AbstractLogService implements ILogService
2324
constructor(
2425
@IExtHostRpcService rpc: IExtHostRpcService,
2526
@IExtHostInitDataService initData: IExtHostInitDataService,
26-
@IExtHostOutputService extHostOutputService: IExtHostOutputService
2727
) {
2828
super();
29-
const logFile = joinPath(initData.logsLocation, `${ExtensionHostLogFileName}.log`);
3029
this._proxy = rpc.getProxy(MainContext.MainThreadLog);
31-
this._logFile = logFile.toJSON();
30+
this._logFile = initData.logFile.toJSON();
3231
this.setLevel(initData.logLevel);
33-
extHostOutputService.createOutputChannelFromLogFile(localize('name', "Worker Extension Host"), logFile);
3432
}
3533

3634
$setLevel(level: LogLevel): void {
@@ -75,3 +73,18 @@ export class ExtHostLogService extends AbstractLogService implements ILogService
7573

7674
flush(): void { }
7775
}
76+
77+
78+
class ExtHostLogChannelContribution extends Disposable implements IExtHostContribution {
79+
80+
constructor(
81+
@IExtHostInitDataService initData: IExtHostInitDataService,
82+
@IExtHostOutputService outputSerice: IExtHostOutputService,
83+
) {
84+
super();
85+
outputSerice.createOutputChannelFromLogFile(localize('name', "Worker Extension Host"), initData.logFile);
86+
}
87+
88+
}
89+
90+
Registry.as<IExtHostContributionsRegistry>(Extensions.ExtHost).registerExtHostContribution(ExtHostLogChannelContribution);

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

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
import { timeout } from 'vs/base/common/async';
77
import * as errors from 'vs/base/common/errors';
8-
import { DisposableStore } from 'vs/base/common/lifecycle';
8+
import { DisposableStore, toDisposable } from 'vs/base/common/lifecycle';
99
import { URI } from 'vs/base/common/uri';
1010
import { IURITransformer } from 'vs/base/common/uriIpc';
1111
import { IMessagePassingProtocol } from 'vs/base/parts/ipc/common/ipc';
@@ -21,6 +21,10 @@ import { IInstantiationService } from 'vs/platform/instantiation/common/instanti
2121
import { IExtHostRpcService, ExtHostRpcService } from 'vs/workbench/api/common/extHostRpcService';
2222
import { IURITransformerService, URITransformerService } from 'vs/workbench/api/common/extHostUriTransformerService';
2323
import { IExtHostExtensionService, IHostUtils } from 'vs/workbench/api/common/extHostExtensionService';
24+
import { Registry } from 'vs/platform/registry/common/platform';
25+
import { IExtHostContributionsRegistry, Extensions } from 'vs/workbench/api/common/extHostContributions';
26+
import { joinPath } from 'vs/base/common/resources';
27+
import { ExtensionHostLogFileName } from 'vs/workbench/services/extensions/common/extensions';
2428

2529
export interface IExitFn {
2630
(code?: number): any;
@@ -52,13 +56,18 @@ export class ExtensionHostMain {
5256

5357
// bootstrap services
5458
const services = new ServiceCollection(...getSingletonServiceDescriptors());
55-
services.set(IExtHostInitDataService, { _serviceBrand: undefined, ...initData });
59+
services.set(IExtHostInitDataService, { _serviceBrand: undefined, ...initData, logFile: joinPath(initData.logsLocation, `${ExtensionHostLogFileName}.log`) });
5660
services.set(IExtHostRpcService, new ExtHostRpcService(rpcProtocol));
5761
services.set(IURITransformerService, new URITransformerService(uriTransformer));
5862
services.set(IHostUtils, hostUtils);
5963

6064
const instaService: IInstantiationService = new InstantiationService(services, true);
6165

66+
// start ext host contributions
67+
const extHostContributionsRegistry = Registry.as<IExtHostContributionsRegistry>(Extensions.ExtHost);
68+
instaService.invokeFunction(accessor => extHostContributionsRegistry.start(accessor));
69+
this._disposables.add(toDisposable(() => extHostContributionsRegistry.stop()));
70+
6271
// todo@joh
6372
// ugly self - inject
6473
const logService = instaService.invokeFunction(accessor => accessor.get(ILogService));

0 commit comments

Comments
 (0)