提交 2fe9de85 编写于 作者: A Alex Dima

Initialize configuration data through ExtHostConfiguration

上级 57d59ad5
......@@ -6,12 +6,13 @@
import { URI, UriComponents } from 'vs/base/common/uri';
import { IDisposable } from 'vs/base/common/lifecycle';
import { Registry } from 'vs/platform/registry/common/platform';
import { IConfigurationRegistry, Extensions as ConfigurationExtensions, ConfigurationScope } from 'vs/platform/configuration/common/configurationRegistry';
import { IConfigurationRegistry, Extensions as ConfigurationExtensions, ConfigurationScope, getScopes } from 'vs/platform/configuration/common/configurationRegistry';
import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace';
import { IWorkspaceConfigurationService } from 'vs/workbench/services/configuration/common/configuration';
import { MainThreadConfigurationShape, MainContext, ExtHostContext, IExtHostContext, IWorkspaceConfigurationChangeEventData } from '../node/extHost.protocol';
import { MainThreadConfigurationShape, MainContext, ExtHostContext, IExtHostContext, IWorkspaceConfigurationChangeEventData, IConfigurationInitData } from '../node/extHost.protocol';
import { extHostNamedCustomer } from 'vs/workbench/api/electron-browser/extHostCustomers';
import { ConfigurationTarget, IConfigurationChangeEvent, IConfigurationModel } from 'vs/platform/configuration/common/configuration';
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
@extHostNamedCustomer(MainContext.MainThreadConfiguration)
export class MainThreadConfiguration implements MainThreadConfigurationShape {
......@@ -21,15 +22,26 @@ export class MainThreadConfiguration implements MainThreadConfigurationShape {
constructor(
extHostContext: IExtHostContext,
@IWorkspaceContextService private readonly _workspaceContextService: IWorkspaceContextService,
@IWorkspaceConfigurationService private readonly configurationService: IWorkspaceConfigurationService
@IWorkspaceConfigurationService private readonly configurationService: IWorkspaceConfigurationService,
@IEnvironmentService private readonly _environmentService: IEnvironmentService,
) {
const proxy = extHostContext.getProxy(ExtHostContext.ExtHostConfiguration);
proxy.$initializeConfiguration(this._getConfigurationData());
this._configurationListener = configurationService.onDidChangeConfiguration(e => {
proxy.$acceptConfigurationChanged(configurationService.getConfigurationData(), this.toConfigurationChangeEventData(e));
proxy.$acceptConfigurationChanged(this._getConfigurationData(), this.toConfigurationChangeEventData(e));
});
}
private _getConfigurationData(): IConfigurationInitData {
const configurationData: IConfigurationInitData = { ...this.configurationService.getConfigurationData(), configurationScopes: {} };
// Send configurations scopes only in development mode.
if (!this._environmentService.isBuilt || this._environmentService.isExtensionDevelopment) {
configurationData.configurationScopes = getScopes();
}
return configurationData;
}
public dispose(): void {
this._configurationListener.dispose();
}
......
......@@ -24,7 +24,7 @@ import { ExtHostApiCommands } from 'vs/workbench/api/node/extHostApiCommands';
import { ExtHostClipboard } from 'vs/workbench/api/node/extHostClipboard';
import { ExtHostCommands } from 'vs/workbench/api/node/extHostCommands';
import { ExtHostComments } from 'vs/workbench/api/node/extHostComments';
import { ExtHostConfiguration } from 'vs/workbench/api/node/extHostConfiguration';
import { ExtHostConfiguration, ExtHostConfigProvider } from 'vs/workbench/api/node/extHostConfiguration';
import { ExtHostDebugService } from 'vs/workbench/api/node/extHostDebugService';
import { ExtHostDecorations } from 'vs/workbench/api/node/extHostDecorations';
import { ExtHostDiagnostics } from 'vs/workbench/api/node/extHostDiagnostics';
......@@ -66,7 +66,7 @@ import * as vscode from 'vscode';
import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions';
export interface IExtensionApiFactory {
(extension: IExtensionDescription, registry: ExtensionDescriptionRegistry): typeof vscode;
(extension: IExtensionDescription, registry: ExtensionDescriptionRegistry, configProvider: ExtHostConfigProvider): typeof vscode;
}
function proposedApiFunction<T>(extension: IExtensionDescription, fn: T): T {
......@@ -142,7 +142,7 @@ export function createApiFactory(
// Register API-ish commands
ExtHostApiCommands.register(extHostCommands);
return function (extension: IExtensionDescription, extensionRegistry: ExtensionDescriptionRegistry): typeof vscode {
return function (extension: IExtensionDescription, extensionRegistry: ExtensionDescriptionRegistry, configProvider: ExtHostConfigProvider): typeof vscode {
// Check document selectors for being overly generic. Technically this isn't a problem but
// in practice many extensions say they support `fooLang` but need fs-access to do so. Those
......@@ -598,11 +598,11 @@ export function createApiFactory(
return extHostDocumentSaveParticipant.getOnWillSaveTextDocumentEvent(extension)(listener, thisArgs, disposables);
},
onDidChangeConfiguration: (listener: (_: any) => any, thisArgs?: any, disposables?: extHostTypes.Disposable[]) => {
return extHostConfiguration.onDidChangeConfiguration(listener, thisArgs, disposables);
return configProvider.onDidChangeConfiguration(listener, thisArgs, disposables);
},
getConfiguration(section?: string, resource?: vscode.Uri): vscode.WorkspaceConfiguration {
resource = arguments.length === 1 ? undefined : resource;
return extHostConfiguration.getConfiguration(section, resource, extension.identifier);
return configProvider.getConfiguration(section, resource, extension.identifier);
},
registerTextDocumentContentProvider(scheme: string, provider: vscode.TextDocumentContentProvider) {
return extHostDocumentContentProviders.registerTextDocumentContentProvider(scheme, provider);
......@@ -865,11 +865,11 @@ class Extension<T> implements vscode.Extension<T> {
}
}
export function initializeExtensionApi(extensionService: ExtHostExtensionService, apiFactory: IExtensionApiFactory, extensionRegistry: ExtensionDescriptionRegistry): Promise<void> {
return extensionService.getExtensionPathIndex().then(trie => defineAPI(apiFactory, trie, extensionRegistry));
export function initializeExtensionApi(extensionService: ExtHostExtensionService, apiFactory: IExtensionApiFactory, extensionRegistry: ExtensionDescriptionRegistry, configProvider: ExtHostConfigProvider): Promise<void> {
return extensionService.getExtensionPathIndex().then(trie => defineAPI(apiFactory, trie, extensionRegistry, configProvider));
}
function defineAPI(factory: IExtensionApiFactory, extensionPaths: TernarySearchTree<IExtensionDescription>, extensionRegistry: ExtensionDescriptionRegistry): void {
function defineAPI(factory: IExtensionApiFactory, extensionPaths: TernarySearchTree<IExtensionDescription>, extensionRegistry: ExtensionDescriptionRegistry, configProvider: ExtHostConfigProvider): void {
// each extension is meant to get its own api implementation
const extApiImpl = new Map<string, typeof vscode>();
......@@ -887,7 +887,7 @@ function defineAPI(factory: IExtensionApiFactory, extensionPaths: TernarySearchT
if (ext) {
let apiImpl = extApiImpl.get(ExtensionIdentifier.toKey(ext.identifier));
if (!apiImpl) {
apiImpl = factory(ext, extensionRegistry);
apiImpl = factory(ext, extensionRegistry, configProvider);
extApiImpl.set(ExtensionIdentifier.toKey(ext.identifier), apiImpl);
}
return apiImpl;
......@@ -898,7 +898,7 @@ function defineAPI(factory: IExtensionApiFactory, extensionPaths: TernarySearchT
let extensionPathsPretty = '';
extensionPaths.forEach((value, index) => extensionPathsPretty += `\t${index} -> ${value.identifier.value}\n`);
console.warn(`Could not identify extension for 'vscode' require call from ${parent.filename}. These are the extension path mappings: \n${extensionPathsPretty}`);
defaultApiImpl = factory(nullExtensionDescription, extensionRegistry);
defaultApiImpl = factory(nullExtensionDescription, extensionRegistry, configProvider);
}
return defaultApiImpl;
};
......
......@@ -67,7 +67,6 @@ export interface IInitData {
environment: IEnvironment;
workspace: IWorkspaceData;
extensions: IExtensionDescription[];
configuration: IConfigurationInitData;
telemetryInfo: ITelemetryInfo;
logLevel: LogLevel;
logsLocation: URI;
......@@ -632,7 +631,8 @@ export interface ExtHostCommandsShape {
}
export interface ExtHostConfigurationShape {
$acceptConfigurationChanged(data: IConfigurationData, eventData: IWorkspaceConfigurationChangeEventData): void;
$initializeConfiguration(data: IConfigurationInitData): void;
$acceptConfigurationChanged(data: IConfigurationInitData, eventData: IWorkspaceConfigurationChangeEventData): void;
}
export interface ExtHostDiagnosticsShape {
......
......@@ -17,6 +17,7 @@ import { ResourceMap } from 'vs/base/common/map';
import { ConfigurationScope, OVERRIDE_PROPERTY_PATTERN } from 'vs/platform/configuration/common/configurationRegistry';
import { isObject } from 'vs/base/common/types';
import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions';
import { Barrier } from 'vs/base/common/async';
function lookUp(tree: any, key: string) {
if (key) {
......@@ -39,6 +40,34 @@ type ConfigurationInspect<T> = {
export class ExtHostConfiguration implements ExtHostConfigurationShape {
private readonly _proxy: MainThreadConfigurationShape;
private readonly _extHostWorkspace: ExtHostWorkspace;
private readonly _barrier: Barrier;
private _actual: ExtHostConfigProvider;
constructor(proxy: MainThreadConfigurationShape, extHostWorkspace: ExtHostWorkspace) {
this._proxy = proxy;
this._extHostWorkspace = extHostWorkspace;
this._barrier = new Barrier();
this._actual = null;
}
public getConfigProvider(): Promise<ExtHostConfigProvider> {
return this._barrier.wait().then(_ => this._actual);
}
$initializeConfiguration(data: IConfigurationInitData): void {
this._actual = new ExtHostConfigProvider(this._proxy, this._extHostWorkspace, data);
this._barrier.open();
}
$acceptConfigurationChanged(data: IConfigurationInitData, eventData: IWorkspaceConfigurationChangeEventData): void {
this._actual.$acceptConfigurationChanged(data, eventData);
}
}
export class ExtHostConfigProvider {
private readonly _onDidChangeConfiguration = new Emitter<vscode.ConfigurationChangeEvent>();
private readonly _proxy: MainThreadConfigurationShape;
private readonly _extHostWorkspace: ExtHostWorkspace;
......@@ -48,7 +77,7 @@ export class ExtHostConfiguration implements ExtHostConfigurationShape {
constructor(proxy: MainThreadConfigurationShape, extHostWorkspace: ExtHostWorkspace, data: IConfigurationInitData) {
this._proxy = proxy;
this._extHostWorkspace = extHostWorkspace;
this._configuration = ExtHostConfiguration.parse(data);
this._configuration = ExtHostConfigProvider.parse(data);
this._configurationScopes = data.configurationScopes;
}
......@@ -56,8 +85,9 @@ export class ExtHostConfiguration implements ExtHostConfigurationShape {
return this._onDidChangeConfiguration && this._onDidChangeConfiguration.event;
}
$acceptConfigurationChanged(data: IConfigurationData, eventData: IWorkspaceConfigurationChangeEventData) {
this._configuration = ExtHostConfiguration.parse(data);
$acceptConfigurationChanged(data: IConfigurationInitData, eventData: IWorkspaceConfigurationChangeEventData) {
this._configuration = ExtHostConfigProvider.parse(data);
this._configurationScopes = data.configurationScopes;
this._onDidChangeConfiguration.fire(this._toConfigurationChangeEvent(eventData));
}
......@@ -220,11 +250,11 @@ export class ExtHostConfiguration implements ExtHostConfigurationShape {
}
private static parse(data: IConfigurationData): Configuration {
const defaultConfiguration = ExtHostConfiguration.parseConfigurationModel(data.defaults);
const userConfiguration = ExtHostConfiguration.parseConfigurationModel(data.user);
const workspaceConfiguration = ExtHostConfiguration.parseConfigurationModel(data.workspace);
const defaultConfiguration = ExtHostConfigProvider.parseConfigurationModel(data.defaults);
const userConfiguration = ExtHostConfigProvider.parseConfigurationModel(data.user);
const workspaceConfiguration = ExtHostConfigProvider.parseConfigurationModel(data.workspace);
const folders: ResourceMap<ConfigurationModel> = Object.keys(data.folders).reduce((result, key) => {
result.set(URI.parse(key), ExtHostConfiguration.parseConfigurationModel(data.folders[key]));
result.set(URI.parse(key), ExtHostConfigProvider.parseConfigurationModel(data.folders[key]));
return result;
}, new ResourceMap<ConfigurationModel>());
return new Configuration(defaultConfiguration, userConfiguration, workspaceConfiguration, folders, new ConfigurationModel(), new ResourceMap<ConfigurationModel>(), false);
......
......@@ -23,7 +23,7 @@ import { ITerminalSettings, IDebuggerContribution, IConfig, IDebugAdapter, IDebu
import { getTerminalLauncher, hasChildProcesses, prepareCommand } from 'vs/workbench/parts/debug/node/terminals';
import { IWorkspaceFolder } from 'vs/platform/workspace/common/workspace';
import { AbstractVariableResolverService } from 'vs/workbench/services/configurationResolver/node/variableResolver';
import { ExtHostConfiguration } from './extHostConfiguration';
import { ExtHostConfiguration, ExtHostConfigProvider } from './extHostConfiguration';
import { convertToVSCPaths, convertToDAPaths, stringToUri, uriToString } from 'vs/workbench/parts/debug/common/debugUtils';
import { ExtHostTerminalService } from 'vs/workbench/api/node/extHostTerminalService';
import { IDisposable } from 'vs/base/common/lifecycle';
......@@ -359,9 +359,10 @@ export class ExtHostDebugService implements ExtHostDebugServiceShape {
return undefined;
}
public $substituteVariables(folderUri: UriComponents | undefined, config: IConfig): Promise<IConfig> {
public async $substituteVariables(folderUri: UriComponents | undefined, config: IConfig): Promise<IConfig> {
const configProvider = await this._configurationService.getConfigProvider();
if (!this._variableResolver) {
this._variableResolver = new ExtHostVariableResolverService(this._workspaceService, this._editorsService, this._configurationService);
this._variableResolver = new ExtHostVariableResolverService(this._workspaceService, this._editorsService, configProvider);
}
let ws: IWorkspaceFolder;
const folder = this.getFolder(folderUri);
......@@ -375,7 +376,7 @@ export class ExtHostDebugService implements ExtHostDebugServiceShape {
}
};
}
return Promise.resolve(this._variableResolver.resolveAny(ws, config));
return this._variableResolver.resolveAny(ws, config);
}
public $startDASession(debugAdapterHandle: number, sessionDto: IDebugSessionDto): Promise<void> {
......@@ -852,7 +853,7 @@ export class ExtHostDebugConsole implements vscode.DebugConsole {
export class ExtHostVariableResolverService extends AbstractVariableResolverService {
constructor(workspaceService: ExtHostWorkspace, editorService: ExtHostDocumentsAndEditors, configurationService: ExtHostConfiguration) {
constructor(workspaceService: ExtHostWorkspace, editorService: ExtHostDocumentsAndEditors, configurationService: ExtHostConfigProvider) {
super({
getFolderUri: (folderName: string): URI => {
const folders = workspaceService.getWorkspaceFolders();
......
......@@ -219,18 +219,25 @@ export class ExtHostExtensionService implements ExtHostExtensionServiceShape {
this._started = false;
initializeExtensionApi(this, this._extensionApiFactory, this._registry).then(() => {
// Do this when extension service exists, but extensions are not being activated yet.
return connectProxyResolver(this._extHostWorkspace, this._extHostConfiguration, this, this._extHostLogService, this._mainThreadTelemetryProxy);
}).then(() => {
this._barrier.open();
});
this._initialize();
if (this._initData.autoStart) {
this._startExtensionHost();
}
}
private async _initialize(): Promise<void> {
try {
const configProvider = await this._extHostConfiguration.getConfigProvider();
await initializeExtensionApi(this, this._extensionApiFactory, this._registry, configProvider);
// Do this when extension service exists, but extensions are not being activated yet.
await connectProxyResolver(this._extHostWorkspace, configProvider, this, this._extHostLogService, this._mainThreadTelemetryProxy);
this._barrier.open();
} catch (err) {
errors.onUnexpectedError(err);
}
}
public async deactivateAll(): Promise<void> {
let allPromises: Promise<void>[] = [];
try {
......
......@@ -9,7 +9,7 @@ import { URI, UriComponents } from 'vs/base/common/uri';
import * as extfs from 'vs/base/node/extfs';
import { ILogService } from 'vs/platform/log/common/log';
import { IFileQuery, IFolderQuery, IRawFileQuery, IRawQuery, IRawTextQuery, ISearchCompleteStats, ITextQuery } from 'vs/platform/search/common/search';
import { ExtHostConfiguration } from 'vs/workbench/api/node/extHostConfiguration';
import { ExtHostConfiguration, ExtHostConfigProvider } from 'vs/workbench/api/node/extHostConfiguration';
import { FileIndexSearchManager } from 'vs/workbench/api/node/extHostSearch.fileIndex';
import { FileSearchManager } from 'vs/workbench/services/search/node/fileSearchManager';
import { SearchService } from 'vs/workbench/services/search/node/rawSearchService';
......@@ -46,7 +46,9 @@ export class ExtHostSearch implements ExtHostSearchShape {
this._fileSearchManager = new FileSearchManager();
this._fileIndexSearchManager = new FileIndexSearchManager();
registerEHProviders(this, _logService, configService);
configService.getConfigProvider().then((configProvider) => {
registerEHProviders(this, _logService, configProvider);
});
}
private _transformScheme(scheme: string): string {
......@@ -176,7 +178,7 @@ export class ExtHostSearch implements ExtHostSearchShape {
}
}
function registerEHProviders(extHostSearch: ExtHostSearch, logService: ILogService, configService: ExtHostConfiguration) {
function registerEHProviders(extHostSearch: ExtHostSearch, logService: ILogService, configService: ExtHostConfigProvider) {
if (configService.getConfiguration('searchRipgrep').enable || configService.getConfiguration('search').runInExtensionHost) {
const outputChannel = new OutputChannel(logService);
extHostSearch.registerTextSearchProvider('file', new RipgrepSearchProvider(outputChannel));
......
......@@ -471,14 +471,15 @@ export class ExtHostTask implements ExtHostTaskShape {
});
}
public $resolveVariables(uriComponents: UriComponents, toResolve: { process?: { name: string; cwd?: string; path?: string }, variables: string[] }): Promise<{ process?: string, variables: { [key: string]: string; } }> {
public async $resolveVariables(uriComponents: UriComponents, toResolve: { process?: { name: string; cwd?: string; path?: string }, variables: string[] }): Promise<{ process?: string, variables: { [key: string]: string; } }> {
const configProvider = await this._configurationService.getConfigProvider();
let uri: URI = URI.revive(uriComponents);
let result = {
process: undefined as string,
variables: Object.create(null)
};
let workspaceFolder = this._workspaceService.resolveWorkspaceFolder(uri);
let resolver = new ExtHostVariableResolverService(this._workspaceService, this._editorService, this._configurationService);
let resolver = new ExtHostVariableResolverService(this._workspaceService, this._editorService, configProvider);
let ws: IWorkspaceFolder = {
uri: workspaceFolder.uri,
name: workspaceFolder.name,
......@@ -504,7 +505,7 @@ export class ExtHostTask implements ExtHostTaskShape {
paths
);
}
return Promise.resolve(result);
return result;
}
private nextHandle(): number {
......
......@@ -374,11 +374,11 @@ export class ExtHostTerminalService implements ExtHostTerminalServiceShape {
}
}
public $createProcess(id: number, shellLaunchConfig: ShellLaunchConfigDto, activeWorkspaceRootUriComponents: UriComponents, cols: number, rows: number): void {
public async $createProcess(id: number, shellLaunchConfig: ShellLaunchConfigDto, activeWorkspaceRootUriComponents: UriComponents, cols: number, rows: number): Promise<void> {
// TODO: This function duplicates a lot of TerminalProcessManager.createProcess, ideally
// they would be merged into a single implementation.
const terminalConfig = this._extHostConfiguration.getConfiguration('terminal.integrated');
const configProvider = await this._extHostConfiguration.getConfigProvider();
const terminalConfig = configProvider.getConfiguration('terminal.integrated');
if (!shellLaunchConfig.executable) {
// TODO: This duplicates some of TerminalConfigHelper.mergeDefaultShellPathAndArgs and should be merged
......
......@@ -77,7 +77,7 @@ export class ExtensionHostMain {
this._extHostLogService.info('extension host started');
this._extHostLogService.trace('initData', initData);
this._extHostConfiguration = new ExtHostConfiguration(rpcProtocol.getProxy(MainContext.MainThreadConfiguration), extHostWorkspace, initData.configuration);
this._extHostConfiguration = new ExtHostConfiguration(rpcProtocol.getProxy(MainContext.MainThreadConfiguration), extHostWorkspace);
this._extensionService = new ExtHostExtensionService(nativeExit, initData, rpcProtocol, extHostWorkspace, this._extHostConfiguration, this._extHostLogService);
// error forwarding and stack trace scanning
......
......@@ -9,7 +9,7 @@ import * as nodeurl from 'url';
import { assign } from 'vs/base/common/objects';
import { ExtHostWorkspace } from 'vs/workbench/api/node/extHostWorkspace';
import { ExtHostConfiguration } from 'vs/workbench/api/node/extHostConfiguration';
import { ExtHostConfigProvider } from 'vs/workbench/api/node/extHostConfiguration';
import { ProxyAgent } from 'vscode-proxy-agent';
import { MainThreadTelemetryShape } from 'vs/workbench/api/node/extHost.protocol';
import { ExtHostLogService } from 'vs/workbench/api/node/extHostLogService';
......@@ -19,13 +19,13 @@ import { URI } from 'vs/base/common/uri';
export function connectProxyResolver(
extHostWorkspace: ExtHostWorkspace,
extHostConfiguration: ExtHostConfiguration,
configProvider: ExtHostConfigProvider,
extensionService: ExtHostExtensionService,
extHostLogService: ExtHostLogService,
mainThreadTelemetry: MainThreadTelemetryShape
) {
const agent = createProxyAgent(extHostWorkspace, extHostConfiguration, extHostLogService, mainThreadTelemetry);
const lookup = createPatchedModules(extHostConfiguration, agent);
const agent = createProxyAgent(extHostWorkspace, configProvider, extHostLogService, mainThreadTelemetry);
const lookup = createPatchedModules(configProvider, agent);
return configureModuleLoading(extensionService, lookup);
}
......@@ -33,14 +33,14 @@ const maxCacheEntries = 5000; // Cache can grow twice that much due to 'oldCache
function createProxyAgent(
extHostWorkspace: ExtHostWorkspace,
extHostConfiguration: ExtHostConfiguration,
configProvider: ExtHostConfigProvider,
extHostLogService: ExtHostLogService,
mainThreadTelemetry: MainThreadTelemetryShape
) {
let settingsProxy = proxyFromConfigURL(extHostConfiguration.getConfiguration('http')
let settingsProxy = proxyFromConfigURL(configProvider.getConfiguration('http')
.get<string>('proxy'));
extHostConfiguration.onDidChangeConfiguration(e => {
settingsProxy = proxyFromConfigURL(extHostConfiguration.getConfiguration('http')
configProvider.onDidChangeConfiguration(e => {
settingsProxy = proxyFromConfigURL(configProvider.getConfiguration('http')
.get<string>('proxy'));
});
const env = process.env;
......@@ -177,13 +177,13 @@ function proxyFromConfigURL(configURL: string) {
return undefined;
}
function createPatchedModules(extHostConfiguration: ExtHostConfiguration, agent: http.Agent) {
function createPatchedModules(configProvider: ExtHostConfigProvider, agent: http.Agent) {
const setting = {
config: extHostConfiguration.getConfiguration('http')
config: configProvider.getConfiguration('http')
.get<string>('proxySupport') || 'off'
};
extHostConfiguration.onDidChangeConfiguration(e => {
setting.config = extHostConfiguration.getConfiguration('http')
configProvider.onDidChangeConfiguration(e => {
setting.config = configProvider.getConfiguration('http')
.get<string>('proxySupport') || 'off';
});
......
......@@ -22,7 +22,6 @@ import { findFreePort, randomPort } from 'vs/base/node/ports';
import { IMessagePassingProtocol } from 'vs/base/parts/ipc/node/ipc';
import { Protocol, generateRandomPipeName, BufferedProtocol } from 'vs/base/parts/ipc/node/ipc.net';
import { IBroadcast, IBroadcastService } from 'vs/platform/broadcast/electron-browser/broadcastService';
import { getScopes } from 'vs/platform/configuration/common/configurationRegistry';
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
import { EXTENSION_ATTACH_BROADCAST_CHANNEL, EXTENSION_CLOSE_EXTHOST_BROADCAST_CHANNEL, EXTENSION_LOG_BROADCAST_CHANNEL, EXTENSION_RELOAD_BROADCAST_CHANNEL, EXTENSION_TERMINATE_BROADCAST_CHANNEL } from 'vs/platform/extensions/common/extensionHost';
import { ILabelService } from 'vs/platform/label/common/label';
......@@ -33,9 +32,8 @@ import { INotificationService, Severity } from 'vs/platform/notification/common/
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { IWindowService, IWindowsService } from 'vs/platform/windows/common/windows';
import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace';
import { IConfigurationInitData, IInitData } from 'vs/workbench/api/node/extHost.protocol';
import { IInitData } from 'vs/workbench/api/node/extHost.protocol';
import { MessageType, createMessageOfType, isMessageOfType } from 'vs/workbench/common/extensionHostProtocol';
import { IWorkspaceConfigurationService } from 'vs/workbench/services/configuration/common/configuration';
import { ICrashReporterService } from 'vs/workbench/services/crashReporter/electron-browser/crashReporterService';
import { IExtensionDescription } from 'vs/workbench/services/extensions/common/extensions';
......@@ -102,7 +100,6 @@ export class ExtensionHostProcessWorker implements IExtensionHostStarter {
@IBroadcastService private readonly _broadcastService: IBroadcastService,
@ILifecycleService private readonly _lifecycleService: ILifecycleService,
@IEnvironmentService private readonly _environmentService: IEnvironmentService,
@IWorkspaceConfigurationService private readonly _configurationService: IWorkspaceConfigurationService,
@ITelemetryService private readonly _telemetryService: ITelemetryService,
@ICrashReporterService private readonly _crashReporterService: ICrashReporterService,
@ILogService private readonly _logService: ILogService,
......@@ -415,7 +412,6 @@ export class ExtensionHostProcessWorker implements IExtensionHostStarter {
private _createExtHostInitData(): Promise<IInitData> {
return Promise.all([this._telemetryService.getTelemetryInfo(), this._extensions])
.then(([telemetryInfo, extensionDescriptions]) => {
const configurationData: IConfigurationInitData = { ...this._configurationService.getConfigurationData(), configurationScopes: {} };
const workspace = this._contextService.getWorkspace();
const r: IInitData = {
commit: product.commit,
......@@ -435,8 +431,6 @@ export class ExtensionHostProcessWorker implements IExtensionHostStarter {
name: this._labelService.getWorkspaceLabel(workspace)
},
extensions: extensionDescriptions,
// Send configurations scopes only in development mode.
configuration: !this._environmentService.isBuilt || this._environmentService.isExtensionDevelopment ? { ...configurationData, configurationScopes: getScopes() } : configurationData,
telemetryInfo,
logLevel: this._logService.getLevel(),
logsLocation: this._extensionHostLogsLocation,
......
......@@ -412,11 +412,13 @@ export class ExtensionService extends Disposable implements IExtensionService {
const extensionHost = this._extensionHostProcessManagers[0];
const extensions = await this._extensionScanner.scannedExtensions;
const enabledExtensions = await this._getRuntimeExtensions(extensions);
this._handleExtensionPoints(enabledExtensions);
extensionHost.start(enabledExtensions.map(extension => extension.identifier));
this._onHasExtensions(enabledExtensions);
this._releaseBarrier();
}
private _onHasExtensions(allExtensions: IExtensionDescription[]): void {
private _handleExtensionPoints(allExtensions: IExtensionDescription[]): void {
this._registry = new ExtensionDescriptionRegistry(allExtensions);
let availableExtensions = this._registry.getAllExtensionDescriptions();
......@@ -427,11 +429,13 @@ export class ExtensionService extends Disposable implements IExtensionService {
for (let i = 0, len = extensionPoints.length; i < len; i++) {
ExtensionService._handleExtensionPoint(extensionPoints[i], availableExtensions, messageHandler);
}
}
private _releaseBarrier(): void {
perf.mark('extensionHostReady');
this._installedExtensionsReady.open();
this._onDidRegisterExtensions.fire(undefined);
this._onDidChangeExtensionsStatus.fire(availableExtensions.map(e => e.identifier));
this._onDidChangeExtensionsStatus.fire(this._registry.getAllExtensionDescriptions().map(e => e.identifier));
}
private _getRuntimeExtensions(allExtensions: IExtensionDescription[]): Promise<IExtensionDescription[]> {
......
......@@ -6,7 +6,7 @@
import * as assert from 'assert';
import { URI } from 'vs/base/common/uri';
import { ExtHostWorkspace } from 'vs/workbench/api/node/extHostWorkspace';
import { ExtHostConfiguration } from 'vs/workbench/api/node/extHostConfiguration';
import { ExtHostConfigProvider } from 'vs/workbench/api/node/extHostConfiguration';
import { MainThreadConfigurationShape, IConfigurationInitData } from 'vs/workbench/api/node/extHost.protocol';
import { ConfigurationModel } from 'vs/platform/configuration/common/configurationModels';
import { TestRPCProtocol } from './testRPCProtocol';
......@@ -31,7 +31,7 @@ suite('ExtHostConfiguration', function () {
if (!shape) {
shape = new class extends mock<MainThreadConfigurationShape>() { };
}
return new ExtHostConfiguration(shape, new ExtHostWorkspace(new TestRPCProtocol(), null, new NullLogService(), new Counter()), createConfigurationData(contents));
return new ExtHostConfigProvider(shape, new ExtHostWorkspace(new TestRPCProtocol(), null, new NullLogService(), new Counter()), createConfigurationData(contents));
}
function createConfigurationData(contents: any): IConfigurationInitData {
......@@ -263,7 +263,7 @@ suite('ExtHostConfiguration', function () {
});
test('inspect in no workspace context', function () {
const testObject = new ExtHostConfiguration(
const testObject = new ExtHostConfigProvider(
new class extends mock<MainThreadConfigurationShape>() { },
new ExtHostWorkspace(new TestRPCProtocol(), null, new NullLogService(), new Counter()),
{
......@@ -306,7 +306,7 @@ suite('ExtHostConfiguration', function () {
}
}, ['editor.wordWrap']);
folders[workspaceUri.toString()] = workspace;
const testObject = new ExtHostConfiguration(
const testObject = new ExtHostConfigProvider(
new class extends mock<MainThreadConfigurationShape>() { },
new ExtHostWorkspace(new TestRPCProtocol(), {
'id': 'foo',
......@@ -380,7 +380,7 @@ suite('ExtHostConfiguration', function () {
}, ['editor.wordWrap']);
folders[thirdRoot.toString()] = new ConfigurationModel({}, []);
const testObject = new ExtHostConfiguration(
const testObject = new ExtHostConfigProvider(
new class extends mock<MainThreadConfigurationShape>() { },
new ExtHostWorkspace(new TestRPCProtocol(), {
'id': 'foo',
......@@ -589,7 +589,7 @@ suite('ExtHostConfiguration', function () {
test('configuration change event', (done) => {
const workspaceFolder = aWorkspaceFolder(URI.file('folder1'), 0);
const testObject = new ExtHostConfiguration(
const testObject = new ExtHostConfigProvider(
new class extends mock<MainThreadConfigurationShape>() { },
new ExtHostWorkspace(new TestRPCProtocol(), {
'id': 'foo',
......
......@@ -61,8 +61,12 @@ class MockMainThreadSearch implements MainThreadSearchShape {
}
class MockExtHostConfiguration {
getConfiguration(section?: string, resource?: URI, extensionId?: string): vscode.WorkspaceConfiguration {
return <vscode.WorkspaceConfiguration>{};
getConfigProvider(): Promise<any> {
return Promise.resolve({
getConfiguration: (section?: string, resource?: URI, extensionId?: string): vscode.WorkspaceConfiguration => {
return <vscode.WorkspaceConfiguration>{};
}
});
}
}
......
......@@ -14,9 +14,13 @@ import { MainThreadConfiguration } from 'vs/workbench/api/electron-browser/mainT
import { SingleProxyRPCProtocol } from './testRPCProtocol';
import { IConfigurationService, ConfigurationTarget } from 'vs/platform/configuration/common/configuration';
import { WorkspaceService } from 'vs/workbench/services/configuration/node/configurationService';
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
suite('MainThreadConfiguration', function () {
let proxy = {
$initializeConfiguration: () => { }
};
let instantiationService: TestInstantiationService;
let target: sinon.SinonSpy;
......@@ -50,11 +54,14 @@ suite('MainThreadConfiguration', function () {
instantiationService.stub(IConfigurationService, 'onDidUpdateConfiguration', sinon.mock());
instantiationService.stub(IConfigurationService, 'onDidChangeConfiguration', sinon.mock());
instantiationService.stub(IConfigurationService, 'updateValue', target);
instantiationService.stub(IEnvironmentService, {
isBuilt: false
});
});
test('update resource configuration without configuration target defaults to workspace in multi root workspace when no resource is provided', function () {
instantiationService.stub(IWorkspaceContextService, <IWorkspaceContextService>{ getWorkbenchState: () => WorkbenchState.WORKSPACE });
const testObject: MainThreadConfiguration = instantiationService.createInstance(MainThreadConfiguration, SingleProxyRPCProtocol(null));
const testObject: MainThreadConfiguration = instantiationService.createInstance(MainThreadConfiguration, SingleProxyRPCProtocol(proxy));
testObject.$updateConfigurationOption(null, 'extHostConfiguration.resource', 'value', null);
......@@ -63,7 +70,7 @@ suite('MainThreadConfiguration', function () {
test('update resource configuration without configuration target defaults to workspace in folder workspace when resource is provider', function () {
instantiationService.stub(IWorkspaceContextService, <IWorkspaceContextService>{ getWorkbenchState: () => WorkbenchState.FOLDER });
const testObject: MainThreadConfiguration = instantiationService.createInstance(MainThreadConfiguration, SingleProxyRPCProtocol(null));
const testObject: MainThreadConfiguration = instantiationService.createInstance(MainThreadConfiguration, SingleProxyRPCProtocol(proxy));
testObject.$updateConfigurationOption(null, 'extHostConfiguration.resource', 'value', URI.file('abc'));
......@@ -72,7 +79,7 @@ suite('MainThreadConfiguration', function () {
test('update resource configuration without configuration target defaults to workspace in folder workspace when no resource is provider', function () {
instantiationService.stub(IWorkspaceContextService, <IWorkspaceContextService>{ getWorkbenchState: () => WorkbenchState.FOLDER });
const testObject: MainThreadConfiguration = instantiationService.createInstance(MainThreadConfiguration, SingleProxyRPCProtocol(null));
const testObject: MainThreadConfiguration = instantiationService.createInstance(MainThreadConfiguration, SingleProxyRPCProtocol(proxy));
testObject.$updateConfigurationOption(null, 'extHostConfiguration.resource', 'value', null);
......@@ -81,7 +88,7 @@ suite('MainThreadConfiguration', function () {
test('update window configuration without configuration target defaults to workspace in multi root workspace when no resource is provided', function () {
instantiationService.stub(IWorkspaceContextService, <IWorkspaceContextService>{ getWorkbenchState: () => WorkbenchState.WORKSPACE });
const testObject: MainThreadConfiguration = instantiationService.createInstance(MainThreadConfiguration, SingleProxyRPCProtocol(null));
const testObject: MainThreadConfiguration = instantiationService.createInstance(MainThreadConfiguration, SingleProxyRPCProtocol(proxy));
testObject.$updateConfigurationOption(null, 'extHostConfiguration.window', 'value', null);
......@@ -90,7 +97,7 @@ suite('MainThreadConfiguration', function () {
test('update window configuration without configuration target defaults to workspace in multi root workspace when resource is provided', function () {
instantiationService.stub(IWorkspaceContextService, <IWorkspaceContextService>{ getWorkbenchState: () => WorkbenchState.WORKSPACE });
const testObject: MainThreadConfiguration = instantiationService.createInstance(MainThreadConfiguration, SingleProxyRPCProtocol(null));
const testObject: MainThreadConfiguration = instantiationService.createInstance(MainThreadConfiguration, SingleProxyRPCProtocol(proxy));
testObject.$updateConfigurationOption(null, 'extHostConfiguration.window', 'value', URI.file('abc'));
......@@ -99,7 +106,7 @@ suite('MainThreadConfiguration', function () {
test('update window configuration without configuration target defaults to workspace in folder workspace when resource is provider', function () {
instantiationService.stub(IWorkspaceContextService, <IWorkspaceContextService>{ getWorkbenchState: () => WorkbenchState.FOLDER });
const testObject: MainThreadConfiguration = instantiationService.createInstance(MainThreadConfiguration, SingleProxyRPCProtocol(null));
const testObject: MainThreadConfiguration = instantiationService.createInstance(MainThreadConfiguration, SingleProxyRPCProtocol(proxy));
testObject.$updateConfigurationOption(null, 'extHostConfiguration.window', 'value', URI.file('abc'));
......@@ -108,7 +115,7 @@ suite('MainThreadConfiguration', function () {
test('update window configuration without configuration target defaults to workspace in folder workspace when no resource is provider', function () {
instantiationService.stub(IWorkspaceContextService, <IWorkspaceContextService>{ getWorkbenchState: () => WorkbenchState.FOLDER });
const testObject: MainThreadConfiguration = instantiationService.createInstance(MainThreadConfiguration, SingleProxyRPCProtocol(null));
const testObject: MainThreadConfiguration = instantiationService.createInstance(MainThreadConfiguration, SingleProxyRPCProtocol(proxy));
testObject.$updateConfigurationOption(null, 'extHostConfiguration.window', 'value', null);
......@@ -117,7 +124,7 @@ suite('MainThreadConfiguration', function () {
test('update resource configuration without configuration target defaults to folder', function () {
instantiationService.stub(IWorkspaceContextService, <IWorkspaceContextService>{ getWorkbenchState: () => WorkbenchState.WORKSPACE });
const testObject: MainThreadConfiguration = instantiationService.createInstance(MainThreadConfiguration, SingleProxyRPCProtocol(null));
const testObject: MainThreadConfiguration = instantiationService.createInstance(MainThreadConfiguration, SingleProxyRPCProtocol(proxy));
testObject.$updateConfigurationOption(null, 'extHostConfiguration.resource', 'value', URI.file('abc'));
......@@ -126,7 +133,7 @@ suite('MainThreadConfiguration', function () {
test('update configuration with user configuration target', function () {
instantiationService.stub(IWorkspaceContextService, <IWorkspaceContextService>{ getWorkbenchState: () => WorkbenchState.FOLDER });
const testObject: MainThreadConfiguration = instantiationService.createInstance(MainThreadConfiguration, SingleProxyRPCProtocol(null));
const testObject: MainThreadConfiguration = instantiationService.createInstance(MainThreadConfiguration, SingleProxyRPCProtocol(proxy));
testObject.$updateConfigurationOption(ConfigurationTarget.USER, 'extHostConfiguration.window', 'value', URI.file('abc'));
......@@ -135,7 +142,7 @@ suite('MainThreadConfiguration', function () {
test('update configuration with workspace configuration target', function () {
instantiationService.stub(IWorkspaceContextService, <IWorkspaceContextService>{ getWorkbenchState: () => WorkbenchState.FOLDER });
const testObject: MainThreadConfiguration = instantiationService.createInstance(MainThreadConfiguration, SingleProxyRPCProtocol(null));
const testObject: MainThreadConfiguration = instantiationService.createInstance(MainThreadConfiguration, SingleProxyRPCProtocol(proxy));
testObject.$updateConfigurationOption(ConfigurationTarget.WORKSPACE, 'extHostConfiguration.window', 'value', URI.file('abc'));
......@@ -144,7 +151,7 @@ suite('MainThreadConfiguration', function () {
test('update configuration with folder configuration target', function () {
instantiationService.stub(IWorkspaceContextService, <IWorkspaceContextService>{ getWorkbenchState: () => WorkbenchState.FOLDER });
const testObject: MainThreadConfiguration = instantiationService.createInstance(MainThreadConfiguration, SingleProxyRPCProtocol(null));
const testObject: MainThreadConfiguration = instantiationService.createInstance(MainThreadConfiguration, SingleProxyRPCProtocol(proxy));
testObject.$updateConfigurationOption(ConfigurationTarget.WORKSPACE_FOLDER, 'extHostConfiguration.window', 'value', URI.file('abc'));
......@@ -153,7 +160,7 @@ suite('MainThreadConfiguration', function () {
test('remove resource configuration without configuration target defaults to workspace in multi root workspace when no resource is provided', function () {
instantiationService.stub(IWorkspaceContextService, <IWorkspaceContextService>{ getWorkbenchState: () => WorkbenchState.WORKSPACE });
const testObject: MainThreadConfiguration = instantiationService.createInstance(MainThreadConfiguration, SingleProxyRPCProtocol(null));
const testObject: MainThreadConfiguration = instantiationService.createInstance(MainThreadConfiguration, SingleProxyRPCProtocol(proxy));
testObject.$removeConfigurationOption(null, 'extHostConfiguration.resource', null);
......@@ -162,7 +169,7 @@ suite('MainThreadConfiguration', function () {
test('remove resource configuration without configuration target defaults to workspace in folder workspace when resource is provider', function () {
instantiationService.stub(IWorkspaceContextService, <IWorkspaceContextService>{ getWorkbenchState: () => WorkbenchState.FOLDER });
const testObject: MainThreadConfiguration = instantiationService.createInstance(MainThreadConfiguration, SingleProxyRPCProtocol(null));
const testObject: MainThreadConfiguration = instantiationService.createInstance(MainThreadConfiguration, SingleProxyRPCProtocol(proxy));
testObject.$removeConfigurationOption(null, 'extHostConfiguration.resource', URI.file('abc'));
......@@ -171,7 +178,7 @@ suite('MainThreadConfiguration', function () {
test('remove resource configuration without configuration target defaults to workspace in folder workspace when no resource is provider', function () {
instantiationService.stub(IWorkspaceContextService, <IWorkspaceContextService>{ getWorkbenchState: () => WorkbenchState.FOLDER });
const testObject: MainThreadConfiguration = instantiationService.createInstance(MainThreadConfiguration, SingleProxyRPCProtocol(null));
const testObject: MainThreadConfiguration = instantiationService.createInstance(MainThreadConfiguration, SingleProxyRPCProtocol(proxy));
testObject.$removeConfigurationOption(null, 'extHostConfiguration.resource', null);
......@@ -180,7 +187,7 @@ suite('MainThreadConfiguration', function () {
test('remove window configuration without configuration target defaults to workspace in multi root workspace when no resource is provided', function () {
instantiationService.stub(IWorkspaceContextService, <IWorkspaceContextService>{ getWorkbenchState: () => WorkbenchState.WORKSPACE });
const testObject: MainThreadConfiguration = instantiationService.createInstance(MainThreadConfiguration, SingleProxyRPCProtocol(null));
const testObject: MainThreadConfiguration = instantiationService.createInstance(MainThreadConfiguration, SingleProxyRPCProtocol(proxy));
testObject.$removeConfigurationOption(null, 'extHostConfiguration.window', null);
......@@ -189,7 +196,7 @@ suite('MainThreadConfiguration', function () {
test('remove window configuration without configuration target defaults to workspace in multi root workspace when resource is provided', function () {
instantiationService.stub(IWorkspaceContextService, <IWorkspaceContextService>{ getWorkbenchState: () => WorkbenchState.WORKSPACE });
const testObject: MainThreadConfiguration = instantiationService.createInstance(MainThreadConfiguration, SingleProxyRPCProtocol(null));
const testObject: MainThreadConfiguration = instantiationService.createInstance(MainThreadConfiguration, SingleProxyRPCProtocol(proxy));
testObject.$removeConfigurationOption(null, 'extHostConfiguration.window', URI.file('abc'));
......@@ -198,7 +205,7 @@ suite('MainThreadConfiguration', function () {
test('remove window configuration without configuration target defaults to workspace in folder workspace when resource is provider', function () {
instantiationService.stub(IWorkspaceContextService, <IWorkspaceContextService>{ getWorkbenchState: () => WorkbenchState.FOLDER });
const testObject: MainThreadConfiguration = instantiationService.createInstance(MainThreadConfiguration, SingleProxyRPCProtocol(null));
const testObject: MainThreadConfiguration = instantiationService.createInstance(MainThreadConfiguration, SingleProxyRPCProtocol(proxy));
testObject.$removeConfigurationOption(null, 'extHostConfiguration.window', URI.file('abc'));
......@@ -207,7 +214,7 @@ suite('MainThreadConfiguration', function () {
test('remove window configuration without configuration target defaults to workspace in folder workspace when no resource is provider', function () {
instantiationService.stub(IWorkspaceContextService, <IWorkspaceContextService>{ getWorkbenchState: () => WorkbenchState.FOLDER });
const testObject: MainThreadConfiguration = instantiationService.createInstance(MainThreadConfiguration, SingleProxyRPCProtocol(null));
const testObject: MainThreadConfiguration = instantiationService.createInstance(MainThreadConfiguration, SingleProxyRPCProtocol(proxy));
testObject.$removeConfigurationOption(null, 'extHostConfiguration.window', null);
......@@ -216,7 +223,7 @@ suite('MainThreadConfiguration', function () {
test('remove configuration without configuration target defaults to folder', function () {
instantiationService.stub(IWorkspaceContextService, <IWorkspaceContextService>{ getWorkbenchState: () => WorkbenchState.WORKSPACE });
const testObject: MainThreadConfiguration = instantiationService.createInstance(MainThreadConfiguration, SingleProxyRPCProtocol(null));
const testObject: MainThreadConfiguration = instantiationService.createInstance(MainThreadConfiguration, SingleProxyRPCProtocol(proxy));
testObject.$removeConfigurationOption(null, 'extHostConfiguration.resource', URI.file('abc'));
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册