提交 aa2fd63b 编写于 作者: S Sandeep Somavarapu

#13357 Move extensions scanning to renderer

上级 51c91003
...@@ -10,10 +10,8 @@ import * as crypto from 'crypto'; ...@@ -10,10 +10,8 @@ import * as crypto from 'crypto';
import nls = require('vs/nls'); import nls = require('vs/nls');
import pfs = require('vs/base/node/pfs'); import pfs = require('vs/base/node/pfs');
import URI from 'vs/base/common/uri';
import { TPromise } from 'vs/base/common/winjs.base'; import { TPromise } from 'vs/base/common/winjs.base';
import paths = require('vs/base/common/paths'); import paths = require('vs/base/common/paths');
import pkg from 'vs/platform/package';
import { IExtensionDescription } from 'vs/platform/extensions/common/extensions'; import { IExtensionDescription } from 'vs/platform/extensions/common/extensions';
import { ExtensionsRegistry } from 'vs/platform/extensions/common/extensionsRegistry'; import { ExtensionsRegistry } from 'vs/platform/extensions/common/extensionsRegistry';
import { ExtHostAPIImplementation, defineAPI } from 'vs/workbench/api/node/extHost.api.impl'; import { ExtHostAPIImplementation, defineAPI } from 'vs/workbench/api/node/extHost.api.impl';
...@@ -21,14 +19,9 @@ import { IMainProcessExtHostIPC } from 'vs/platform/extensions/common/ipcRemoteC ...@@ -21,14 +19,9 @@ import { IMainProcessExtHostIPC } from 'vs/platform/extensions/common/ipcRemoteC
import { ExtHostExtensionService } from 'vs/workbench/api/node/extHostExtensionService'; import { ExtHostExtensionService } from 'vs/workbench/api/node/extHostExtensionService';
import { ExtHostThreadService } from 'vs/workbench/services/thread/common/extHostThreadService'; import { ExtHostThreadService } from 'vs/workbench/services/thread/common/extHostThreadService';
import { RemoteTelemetryService } from 'vs/workbench/api/node/extHostTelemetry'; import { RemoteTelemetryService } from 'vs/workbench/api/node/extHostTelemetry';
import { ExtensionScanner, MessagesCollector } from 'vs/workbench/node/extensionPoints';
import { IWorkspaceContextService, WorkspaceContextService } from 'vs/platform/workspace/common/workspace'; import { IWorkspaceContextService, WorkspaceContextService } from 'vs/platform/workspace/common/workspace';
import * as errors from 'vs/base/common/errors'; import * as errors from 'vs/base/common/errors';
const DIRNAME = URI.parse(require.toUrl('./')).fsPath;
const BASE_PATH = paths.normalize(paths.join(DIRNAME, '../../../..'));
const BUILTIN_EXTENSIONS_PATH = paths.join(BASE_PATH, 'extensions');
export interface IEnvironment { export interface IEnvironment {
appSettingsHome: string; appSettingsHome: string;
disableExtensions: boolean; disableExtensions: boolean;
...@@ -44,6 +37,7 @@ export interface IInitData { ...@@ -44,6 +37,7 @@ export interface IInitData {
workspace: any; workspace: any;
options: any; options: any;
}; };
extensions: IExtensionDescription[];
} }
const nativeExit = process.exit.bind(process); const nativeExit = process.exit.bind(process);
...@@ -65,11 +59,13 @@ export class ExtensionHostMain { ...@@ -65,11 +59,13 @@ export class ExtensionHostMain {
private _contextService: IWorkspaceContextService; private _contextService: IWorkspaceContextService;
private _environment: IEnvironment; private _environment: IEnvironment;
private _extensionService: ExtHostExtensionService; private _extensionService: ExtHostExtensionService;
private _extensions: IExtensionDescription[];
constructor(remoteCom: IMainProcessExtHostIPC, initData: IInitData) { constructor(remoteCom: IMainProcessExtHostIPC, initData: IInitData) {
this._isTerminating = false; this._isTerminating = false;
this._environment = initData.environment; this._environment = initData.environment;
this._extensions = initData.extensions;
this._contextService = new WorkspaceContextService(initData.contextService.workspace); this._contextService = new WorkspaceContextService(initData.contextService.workspace);
const workspaceStoragePath = this._getOrCreateWorkspaceStoragePath(); const workspaceStoragePath = this._getOrCreateWorkspaceStoragePath();
...@@ -80,16 +76,6 @@ export class ExtensionHostMain { ...@@ -80,16 +76,6 @@ export class ExtensionHostMain {
this._extensionService = new ExtHostExtensionService(threadService, telemetryService, { _serviceBrand: 'optionalArgs', workspaceStoragePath }); this._extensionService = new ExtHostExtensionService(threadService, telemetryService, { _serviceBrand: 'optionalArgs', workspaceStoragePath });
// Connect to shared process services
/*
const channel = sharedProcessClient.getChannel<IExtensionManagementChannel>('extensions');
const extensionsService = new ExtensionManagementChannelClient(channel);
if (false && false) {
// TODO: what to do with the ExtensionManagementChannelClient?
console.log(extensionsService);
}
*/
// Create the ext host API // Create the ext host API
defineAPI(new ExtHostAPIImplementation(threadService, this._extensionService, this._contextService, telemetryService)); defineAPI(new ExtHostAPIImplementation(threadService, this._extensionService, this._contextService, telemetryService));
} }
...@@ -142,7 +128,7 @@ export class ExtensionHostMain { ...@@ -142,7 +128,7 @@ export class ExtensionHostMain {
} }
public start(): TPromise<void> { public start(): TPromise<void> {
return this.readExtensions(); return this.registerExtensions();
} }
public terminate(): void { public terminate(): void {
...@@ -177,53 +163,10 @@ export class ExtensionHostMain { ...@@ -177,53 +163,10 @@ export class ExtensionHostMain {
}, 1000); }, 1000);
} }
private readExtensions(): TPromise<void> { private registerExtensions(): TPromise<void> {
let collector = new MessagesCollector(); ExtensionsRegistry.registerExtensions(this._extensions);
this._extensionService.registrationDone([]);
return ExtensionHostMain.scanExtensions(collector, BUILTIN_EXTENSIONS_PATH, !this._environment.disableExtensions ? this._environment.userExtensionsHome : void 0, !this._environment.disableExtensions ? this._environment.extensionDevelopmentPath : void 0, pkg.version) return this.handleEagerExtensions().then(() => this.handleExtensionTests());
.then(null, err => {
collector.error('', err);
return [];
})
.then(extensions => {
// Register & Signal done
ExtensionsRegistry.registerExtensions(extensions);
this._extensionService.registrationDone(collector.getMessages());
})
.then(() => this.handleEagerExtensions())
.then(() => this.handleExtensionTests());
}
private static scanExtensions(collector: MessagesCollector, builtinExtensionsPath: string, userInstallPath: string, extensionDevelopmentPath: string, version: string): TPromise<IExtensionDescription[]> {
const builtinExtensions = ExtensionScanner.scanExtensions(version, collector, builtinExtensionsPath, true);
const userExtensions = !userInstallPath ? TPromise.as([]) : ExtensionScanner.scanExtensions(version, collector, userInstallPath, false);
const developedExtensions = !extensionDevelopmentPath ? TPromise.as([]) : ExtensionScanner.scanOneOrMultipleExtensions(version, collector, extensionDevelopmentPath, false);
return TPromise.join([builtinExtensions, userExtensions, developedExtensions]).then((_: IExtensionDescription[][]) => {
let builtinExtensions = _[0];
let userExtensions = _[1];
let developedExtensions = _[2];
let result: { [extensionId: string]: IExtensionDescription; } = {};
builtinExtensions.forEach((builtinExtension) => {
result[builtinExtension.id] = builtinExtension;
});
userExtensions.forEach((userExtension) => {
if (result.hasOwnProperty(userExtension.id)) {
collector.warn(userExtension.extensionFolderPath, nls.localize('overwritingExtension', "Overwriting extension {0} with {1}.", result[userExtension.id].extensionFolderPath, userExtension.extensionFolderPath));
}
result[userExtension.id] = userExtension;
});
developedExtensions.forEach(developedExtension => {
collector.info('', nls.localize('extensionUnderDevelopment', "Loading development extension at {0}", developedExtension.extensionFolderPath));
if (result.hasOwnProperty(developedExtension.id)) {
collector.warn(developedExtension.extensionFolderPath, nls.localize('overwritingExtension', "Overwriting extension {0} with {1}.", result[developedExtension.id].extensionFolderPath, developedExtension.extensionFolderPath));
}
result[developedExtension.id] = developedExtension;
});
return Object.keys(result).map(name => result[name]);
});
} }
// Handle "eager" activation extensions // Handle "eager" activation extensions
......
...@@ -6,6 +6,8 @@ ...@@ -6,6 +6,8 @@
'use strict'; 'use strict';
import * as nls from 'vs/nls'; import * as nls from 'vs/nls';
import pkg from 'vs/platform/package';
import paths = require('vs/base/common/paths');
import { toErrorMessage } from 'vs/base/common/errorMessage'; import { toErrorMessage } from 'vs/base/common/errorMessage';
import { stringify } from 'vs/base/common/marshalling'; import { stringify } from 'vs/base/common/marshalling';
import * as objects from 'vs/base/common/objects'; import * as objects from 'vs/base/common/objects';
...@@ -26,11 +28,17 @@ import { IThreadService } from 'vs/workbench/services/thread/common/threadServic ...@@ -26,11 +28,17 @@ import { IThreadService } from 'vs/workbench/services/thread/common/threadServic
import { IEnvironmentService } from 'vs/platform/environment/common/environment'; import { IEnvironmentService } from 'vs/platform/environment/common/environment';
import { ReloadWindowAction } from 'vs/workbench/electron-browser/actions'; import { ReloadWindowAction } from 'vs/workbench/electron-browser/actions';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { IExtensionDescription, IMessage } from 'vs/platform/extensions/common/extensions';
import { ExtensionScanner, MessagesCollector } from 'vs/workbench/node/extensionPoints';
export const EXTENSION_LOG_BROADCAST_CHANNEL = 'vscode:extensionLog'; export const EXTENSION_LOG_BROADCAST_CHANNEL = 'vscode:extensionLog';
export const EXTENSION_ATTACH_BROADCAST_CHANNEL = 'vscode:extensionAttach'; export const EXTENSION_ATTACH_BROADCAST_CHANNEL = 'vscode:extensionAttach';
export const EXTENSION_TERMINATE_BROADCAST_CHANNEL = 'vscode:extensionTerminate'; export const EXTENSION_TERMINATE_BROADCAST_CHANNEL = 'vscode:extensionTerminate';
const DIRNAME = URI.parse(require.toUrl('./')).fsPath;
const BASE_PATH = paths.normalize(paths.join(DIRNAME, '../../../../../..'));
const BUILTIN_EXTENSIONS_PATH = paths.join(BASE_PATH, 'extensions');
// Enable to see detailed message communication between window and extension host // Enable to see detailed message communication between window and extension host
const logExtensionHostCommunication = false; const logExtensionHostCommunication = false;
...@@ -243,22 +251,64 @@ class ExtensionHostProcessManager { ...@@ -243,22 +251,64 @@ class ExtensionHostProcessManager {
if (this.initializeTimer) { if (this.initializeTimer) {
window.clearTimeout(this.initializeTimer); window.clearTimeout(this.initializeTimer);
} }
this.scanExtensions().then(extensionDescriptors => {
let initPayload = stringify({ let initPayload = stringify({
parentPid: process.pid, parentPid: process.pid,
environment: { environment: {
appSettingsHome: this.environmentService.appSettingsHome, appSettingsHome: this.environmentService.appSettingsHome,
disableExtensions: this.environmentService.disableExtensions, disableExtensions: this.environmentService.disableExtensions,
userExtensionsHome: this.environmentService.extensionsPath, userExtensionsHome: this.environmentService.extensionsPath,
extensionDevelopmentPath: this.environmentService.extensionDevelopmentPath, extensionDevelopmentPath: this.environmentService.extensionDevelopmentPath,
extensionTestsPath: this.environmentService.extensionTestsPath extensionTestsPath: this.environmentService.extensionTestsPath
}, },
contextService: { contextService: {
workspace: this.contextService.getWorkspace() workspace: this.contextService.getWorkspace()
} },
extensions: extensionDescriptors
});
this.extensionHostProcessHandle.send(initPayload);
}); });
}
private scanExtensions(): TPromise<IExtensionDescription[]> {
const collector = new MessagesCollector();
const version = pkg.version;
const builtinExtensions = ExtensionScanner.scanExtensions(version, collector, BUILTIN_EXTENSIONS_PATH, true);
const userExtensions = this.environmentService.disableExtensions || !this.environmentService.extensionsPath ? TPromise.as([]) : ExtensionScanner.scanExtensions(version, collector, this.environmentService.extensionsPath, false);
const developedExtensions = this.environmentService.disableExtensions || !this.environmentService.extensionDevelopmentPath ? TPromise.as([]) : ExtensionScanner.scanOneOrMultipleExtensions(version, collector, this.environmentService.extensionDevelopmentPath, false);
const isDev = !this.environmentService.isBuilt || !!this.environmentService.extensionDevelopmentPath;
return TPromise.join([builtinExtensions, userExtensions, developedExtensions]).then((extensionDescriptions: IExtensionDescription[][]) => {
let builtinExtensions = extensionDescriptions[0];
let userExtensions = extensionDescriptions[1];
let developedExtensions = extensionDescriptions[2];
let result: { [extensionId: string]: IExtensionDescription; } = {};
builtinExtensions.forEach((builtinExtension) => {
result[builtinExtension.id] = builtinExtension;
});
userExtensions.forEach((userExtension) => {
if (result.hasOwnProperty(userExtension.id)) {
collector.warn(userExtension.extensionFolderPath, nls.localize('overwritingExtension', "Overwriting extension {0} with {1}.", result[userExtension.id].extensionFolderPath, userExtension.extensionFolderPath));
}
result[userExtension.id] = userExtension;
});
developedExtensions.forEach(developedExtension => {
collector.info('', nls.localize('extensionUnderDevelopment', "Loading development extension at {0}", developedExtension.extensionFolderPath));
if (result.hasOwnProperty(developedExtension.id)) {
collector.warn(developedExtension.extensionFolderPath, nls.localize('overwritingExtension', "Overwriting extension {0} with {1}.", result[developedExtension.id].extensionFolderPath, developedExtension.extensionFolderPath));
}
result[developedExtension.id] = developedExtension;
});
this.extensionHostProcessHandle.send(initPayload); return Object.keys(result).map(name => result[name]);
}).then(null, err => {
collector.error('', err);
return [];
}).then(extensions => {
collector.getMessages().forEach(entry => this._handleMessage(entry, isDev));
return extensions;
});
} }
private logExtensionHostMessage(logEntry: ILogEntry) { private logExtensionHostMessage(logEntry: ILogEntry) {
...@@ -369,4 +419,27 @@ class ExtensionHostProcessManager { ...@@ -369,4 +419,27 @@ class ExtensionHostProcessManager {
event.veto(TPromise.timeout(100 /* wait a bit for IPC to get delivered */).then(() => false)); event.veto(TPromise.timeout(100 /* wait a bit for IPC to get delivered */).then(() => false));
} }
} }
private _handleMessage(message: IMessage, isDev: boolean): void {
let messageShown = false;
if (message.type === Severity.Error || message.type === Severity.Warning) {
if (isDev) {
// Only show nasty intrusive messages if doing extension development.
this.messageService.show(message.type, (message.source ? '[' + message.source + ']: ' : '') + message.message);
messageShown = true;
}
}
if (!messageShown) {
switch (message.type) {
case Severity.Error:
console.error(message);
break;
case Severity.Warning:
console.warn(message);
break;
default:
console.log(message);
}
}
}
} }
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册