Initialize configuration data through ExtHostConfiguration

This commit is contained in:
Alex Dima
2019-01-14 17:04:29 +01:00
parent 57d59ad535
commit 2fe9de8511
16 changed files with 155 additions and 93 deletions

View File

@@ -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;
};

View File

@@ -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 {

View File

@@ -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);

View File

@@ -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();

View File

@@ -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 {

View File

@@ -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));

View File

@@ -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 {

View File

@@ -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