Update the extension path tree after $deltaExtensions

This commit is contained in:
Alex Dima 2022-04-20 17:00:44 +03:00
parent b9e8734a7b
commit 3e7fed03dc
No known key found for this signature in database
GPG key ID: 39563C1504FDD0C9
2 changed files with 59 additions and 43 deletions

View file

@ -106,7 +106,7 @@ export abstract class AbstractExtHostExtensionService extends Disposable impleme
private readonly _secretState: ExtHostSecretState;
private readonly _storagePath: IExtensionStoragePaths;
private readonly _activator: ExtensionsActivator;
private _extensionPathIndex: Promise<TernarySearchTree<URI, IExtensionDescription>> | null;
private _extensionPathIndex: Promise<ExtensionPaths> | null;
private readonly _resolvers: { [authorityPrefix: string]: vscode.RemoteAuthorityResolver };
@ -330,9 +330,11 @@ export abstract class AbstractExtHostExtensionService extends Disposable impleme
}
// create trie to enable fast 'filename -> extension id' look up
public async getExtensionPathIndex(): Promise<TernarySearchTree<URI, IExtensionDescription>> {
public async getExtensionPathIndex(): Promise<ExtensionPaths> {
if (!this._extensionPathIndex) {
this._extensionPathIndex = this._createExtensionPathIndex(this._myRegistry.getAllExtensionDescriptions());
this._extensionPathIndex = this._createExtensionPathIndex(this._myRegistry.getAllExtensionDescriptions()).then((searchTree) => {
return new ExtensionPaths(searchTree);
});
}
return this._extensionPathIndex;
}
@ -712,6 +714,11 @@ export abstract class AbstractExtHostExtensionService extends Disposable impleme
}
private _startExtensionHost(): Promise<void> {
console.log(`$startExtensionHost CALLED!`);
console.log(`myExtensions: ${this._myRegistry.getAllExtensionDescriptions().length} extensions`);
console.log(`allExtensions: ${this._globalRegistry.getAllExtensionDescriptions().length} extensions`);
if (this._started) {
throw new Error(`Extension host is already started!`);
}
@ -835,18 +842,28 @@ export abstract class AbstractExtHostExtensionService extends Disposable impleme
return result;
}
public $startExtensionHost(extensionsDelta: IExtensionDescriptionDelta): Promise<void> {
extensionsDelta.toAdd.forEach((extension) => (<any>extension).extensionLocation = URI.revive(extension.extensionLocation));
this._globalRegistry.deltaExtensions(extensionsDelta.toAdd, extensionsDelta.toRemove);
private static _applyExtensionsDelta(oldGlobalRegistry: ExtensionDescriptionRegistry, oldMyRegistry: ExtensionDescriptionRegistry, extensionsDelta: IExtensionDescriptionDelta) {
const globalRegistry = new ExtensionDescriptionRegistry(oldGlobalRegistry.getAllExtensionDescriptions());
globalRegistry.deltaExtensions(extensionsDelta.toAdd, extensionsDelta.toRemove);
const myExtensions = extensionIdentifiersArrayToSet(this._myRegistry.getAllExtensionDescriptions().map(extension => extension.identifier));
const myExtensionsSet = extensionIdentifiersArrayToSet(oldMyRegistry.getAllExtensionDescriptions().map(extension => extension.identifier));
for (const extensionId of extensionsDelta.myToRemove) {
myExtensions.delete(ExtensionIdentifier.toKey(extensionId));
myExtensionsSet.delete(ExtensionIdentifier.toKey(extensionId));
}
for (const extensionId of extensionsDelta.myToAdd) {
myExtensions.add(ExtensionIdentifier.toKey(extensionId));
myExtensionsSet.add(ExtensionIdentifier.toKey(extensionId));
}
this._myRegistry.set(filterExtensions(this._globalRegistry, myExtensions));
const myExtensions = filterExtensions(globalRegistry, myExtensionsSet);
return { globalRegistry, myExtensions };
}
public $startExtensionHost(extensionsDelta: IExtensionDescriptionDelta): Promise<void> {
extensionsDelta.toAdd.forEach((extension) => (<any>extension).extensionLocation = URI.revive(extension.extensionLocation));
const { globalRegistry, myExtensions } = AbstractExtHostExtensionService._applyExtensionsDelta(this._globalRegistry, this._myRegistry, extensionsDelta);
this._globalRegistry.set(globalRegistry.getAllExtensionDescriptions());
this._myRegistry.set(myExtensions);
return this._startExtensionHost();
}
@ -875,32 +892,13 @@ export abstract class AbstractExtHostExtensionService extends Disposable impleme
public async $deltaExtensions(extensionsDelta: IExtensionDescriptionDelta): Promise<void> {
extensionsDelta.toAdd.forEach((extension) => (<any>extension).extensionLocation = URI.revive(extension.extensionLocation));
this._globalRegistry.deltaExtensions(extensionsDelta.toAdd, extensionsDelta.toRemove);
const myExtensions = extensionIdentifiersArrayToSet(this._myRegistry.getAllExtensionDescriptions().map(extension => extension.identifier));
for (const extensionId of extensionsDelta.myToRemove) {
myExtensions.delete(ExtensionIdentifier.toKey(extensionId));
}
for (const extensionId of extensionsDelta.myToAdd) {
myExtensions.add(ExtensionIdentifier.toKey(extensionId));
}
this._myRegistry.set(filterExtensions(this._globalRegistry, myExtensions));
console.log(`TODO: update the extension path trie!`);
// const trie = await this.getExtensionPathIndex();
// await Promise.all(toRemove.map(async (extensionId) => {
// const extensionDescription = this._myRegistry.getExtensionDescription(extensionId);
// if (extensionDescription) {
// trie.delete(await this._realPathExtensionUri(extensionDescription.extensionLocation));
// }
// }));
// await Promise.all(toAdd.map(async (extensionDescription) => {
// const realpathUri = await this._realPathExtensionUri(extensionDescription.extensionLocation);
// trie.set(realpathUri, extensionDescription);
// }));
// First build up and update the trie and only afterwards apply the delta
const { globalRegistry, myExtensions } = AbstractExtHostExtensionService._applyExtensionsDelta(this._globalRegistry, this._myRegistry, extensionsDelta);
const newSearchTree = await this._createExtensionPathIndex(myExtensions);
const extensionsPaths = await this.getExtensionPathIndex();
extensionsPaths.setSearchTree(newSearchTree);
this._globalRegistry.set(globalRegistry.getAllExtensionDescriptions());
this._myRegistry.set(myExtensions);
return Promise.resolve(undefined);
}
@ -972,7 +970,7 @@ export interface IExtHostExtensionService extends AbstractExtHostExtensionServic
activateByIdWithErrors(extensionId: ExtensionIdentifier, reason: ExtensionActivationReason): Promise<void>;
getExtensionExports(extensionId: ExtensionIdentifier): IExtensionAPI | null | undefined;
getExtensionRegistry(): Promise<ExtensionDescriptionRegistry>;
getExtensionPathIndex(): Promise<TernarySearchTree<URI, IExtensionDescription>>;
getExtensionPathIndex(): Promise<ExtensionPaths>;
registerRemoteAuthorityResolver(authorityPrefix: string, resolver: vscode.RemoteAuthorityResolver): vscode.Disposable;
onDidChangeRemoteConnectionData: Event<void>;
@ -1031,3 +1029,22 @@ function getRemoteAuthorityPrefix(remoteAuthority: string): string {
}
return remoteAuthority.substring(0, plusIndex);
}
export class ExtensionPaths {
constructor(
private _searchTree: TernarySearchTree<URI, IExtensionDescription>
) { }
setSearchTree(searchTree: TernarySearchTree<URI, IExtensionDescription>): void {
this._searchTree = searchTree;
}
findSubstr(key: URI): IExtensionDescription | undefined {
return this._searchTree.findSubstr(key);
}
forEach(callback: (value: IExtensionDescription, index: URI) => any): void {
return this._searchTree.forEach(callback);
}
}

View file

@ -4,19 +4,18 @@
*--------------------------------------------------------------------------------------------*/
import * as performance from 'vs/base/common/performance';
import { TernarySearchTree } from 'vs/base/common/map';
import { URI } from 'vs/base/common/uri';
import { MainThreadTelemetryShape, MainContext } from 'vs/workbench/api/common/extHost.protocol';
import { ExtHostConfigProvider, IExtHostConfiguration } from 'vs/workbench/api/common/extHostConfiguration';
import { nullExtensionDescription } from 'vs/workbench/services/extensions/common/extensions';
import { ExtensionDescriptionRegistry } from 'vs/workbench/services/extensions/common/extensionDescriptionRegistry';
import * as vscode from 'vscode';
import { ExtensionIdentifier, IExtensionDescription } from 'vs/platform/extensions/common/extensions';
import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions';
import { IExtensionApiFactory } from 'vs/workbench/api/common/extHost.api.impl';
import { IExtHostRpcService } from 'vs/workbench/api/common/extHostRpcService';
import { IExtHostInitDataService } from 'vs/workbench/api/common/extHostInitDataService';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { IExtHostExtensionService } from 'vs/workbench/api/common/extHostExtensionService';
import { ExtensionPaths, IExtHostExtensionService } from 'vs/workbench/api/common/extHostExtensionService';
import { platform } from 'vs/base/common/process';
import { ILogService } from 'vs/platform/log/common/log';
import { escapeRegExpCharacters } from 'vs/base/common/strings';
@ -156,7 +155,7 @@ class VSCodeNodeModuleFactory implements INodeModuleFactory {
constructor(
private readonly _apiFactory: IExtensionApiFactory,
private readonly _extensionPaths: TernarySearchTree<URI, IExtensionDescription>,
private readonly _extensionPaths: ExtensionPaths,
private readonly _extensionRegistry: ExtensionDescriptionRegistry,
private readonly _configProvider: ExtHostConfigProvider,
private readonly _logService: ILogService,
@ -208,7 +207,7 @@ class KeytarNodeModuleFactory implements INodeModuleFactory {
private _impl: IKeytarModule;
constructor(
private readonly _extensionPaths: TernarySearchTree<URI, IExtensionDescription>,
private readonly _extensionPaths: ExtensionPaths,
@IExtHostRpcService rpcService: IExtHostRpcService,
@IExtHostInitDataService initData: IExtHostInitDataService,
@ -303,7 +302,7 @@ class OpenNodeModuleFactory implements INodeModuleFactory {
private _mainThreadTelemetry: MainThreadTelemetryShape;
constructor(
private readonly _extensionPaths: TernarySearchTree<URI, IExtensionDescription>,
private readonly _extensionPaths: ExtensionPaths,
private readonly _appUriScheme: string,
@IExtHostRpcService rpcService: IExtHostRpcService,
) {