From cc126dfd8bdc6574b44aeb4eda7c849e748efa39 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Wed, 22 May 2019 18:52:06 +0200 Subject: [PATCH] reuse extension data for deps and pack tree. --- .../extensions/browser/extensionsViewer.ts | 44 ++++ .../contrib/extensions/common/extensions.ts | 9 - .../electron-browser/extensionEditor.ts | 113 ++------ .../node/extensionsWorkbenchService.ts | 70 +---- .../extensionsWorkbenchService.test.ts | 242 ------------------ 5 files changed, 65 insertions(+), 413 deletions(-) diff --git a/src/vs/workbench/contrib/extensions/browser/extensionsViewer.ts b/src/vs/workbench/contrib/extensions/browser/extensionsViewer.ts index 35af370ca9e..be598ddc5dd 100644 --- a/src/vs/workbench/contrib/extensions/browser/extensionsViewer.ts +++ b/src/vs/workbench/contrib/extensions/browser/extensionsViewer.ts @@ -19,6 +19,8 @@ import { IAccessibilityService } from 'vs/platform/accessibility/common/accessib import { IAsyncDataSource, ITreeNode } from 'vs/base/browser/ui/tree/tree'; import { IListVirtualDelegate, IListRenderer } from 'vs/base/browser/ui/list/list'; import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; +import { CancellationToken } from 'vs/base/common/cancellation'; +import { isNonEmptyArray } from 'vs/base/common/arrays'; export interface IExtensionTemplateData { icon: HTMLImageElement; @@ -217,4 +219,46 @@ export class ExtensionsTree extends WorkbenchAsyncDataTree string[]; + private readonly childrenExtensionIds: string[]; + private readonly extensionsWorkbenchService: IExtensionsWorkbenchService; + + constructor(extension: IExtension, parent: IExtensionData | null, getChildrenExtensionIds: (extension: IExtension) => string[], extensionsWorkbenchService: IExtensionsWorkbenchService) { + this.extension = extension; + this.parent = parent; + this.getChildrenExtensionIds = getChildrenExtensionIds; + this.extensionsWorkbenchService = extensionsWorkbenchService; + this.childrenExtensionIds = this.getChildrenExtensionIds(extension); + } + + get hasChildren(): boolean { + return isNonEmptyArray(this.childrenExtensionIds); + } + + async getChildren(): Promise { + if (this.hasChildren) { + const localById = this.extensionsWorkbenchService.local.reduce((result, e) => { result.set(e.identifier.id.toLowerCase(), e); return result; }, new Map()); + const result: IExtension[] = []; + const toQuery: string[] = []; + for (const extensionId of this.childrenExtensionIds) { + const id = extensionId.toLowerCase(); + const local = localById.get(id); + if (local) { + result.push(local); + } else { + toQuery.push(id); + } + } + const galleryResult = await this.extensionsWorkbenchService.queryGallery({ names: this.childrenExtensionIds, pageSize: this.childrenExtensionIds.length }, CancellationToken.None); + result.push(...galleryResult.firstPage); + return result.map(extension => new ExtensionData(extension, this, this.getChildrenExtensionIds, this.extensionsWorkbenchService)); + } + return null; + } } \ No newline at end of file diff --git a/src/vs/workbench/contrib/extensions/common/extensions.ts b/src/vs/workbench/contrib/extensions/common/extensions.ts index ec1999a2b32..ae1ffe0c808 100644 --- a/src/vs/workbench/contrib/extensions/common/extensions.ts +++ b/src/vs/workbench/contrib/extensions/common/extensions.ts @@ -67,14 +67,6 @@ export interface IExtension { readonly isMalicious: boolean; } -export interface IExtensionDependencies { - dependencies: IExtensionDependencies[]; - hasDependencies: boolean; - identifier: string; - extension: IExtension; - dependent: IExtensionDependencies | null; -} - export const SERVICE_ID = 'extensionsWorkbenchService'; export const IExtensionsWorkbenchService = createDecorator(SERVICE_ID); @@ -95,7 +87,6 @@ export interface IExtensionsWorkbenchService { installVersion(extension: IExtension, version: string): Promise; reinstall(extension: IExtension): Promise; setEnablement(extensions: IExtension | IExtension[], enablementState: EnablementState): Promise; - loadDependencies(extension: IExtension, token: CancellationToken): Promise; open(extension: IExtension, sideByside?: boolean): Promise; checkForUpdates(): Promise; allowedBadgeProviders: string[]; diff --git a/src/vs/workbench/contrib/extensions/electron-browser/extensionEditor.ts b/src/vs/workbench/contrib/extensions/electron-browser/extensionEditor.ts index e87adb8c170..3b55b40e836 100644 --- a/src/vs/workbench/contrib/extensions/electron-browser/extensionEditor.ts +++ b/src/vs/workbench/contrib/extensions/electron-browser/extensionEditor.ts @@ -24,7 +24,7 @@ import { IExtensionTipsService } from 'vs/platform/extensionManagement/common/ex import { IExtensionManifest, IKeyBinding, IView, IViewContainer, ExtensionType } from 'vs/platform/extensions/common/extensions'; import { ResolvedKeybinding, KeyMod, KeyCode } from 'vs/base/common/keyCodes'; import { ExtensionsInput } from 'vs/workbench/contrib/extensions/common/extensionsInput'; -import { IExtensionsWorkbenchService, IExtensionsViewlet, VIEWLET_ID, IExtension, IExtensionDependencies, ExtensionContainers } from 'vs/workbench/contrib/extensions/common/extensions'; +import { IExtensionsWorkbenchService, IExtensionsViewlet, VIEWLET_ID, IExtension, ExtensionContainers } from 'vs/workbench/contrib/extensions/common/extensions'; import { RatingsWidget, InstallCountWidget, RemoteBadgeWidget } from 'vs/workbench/contrib/extensions/electron-browser/extensionsWidgets'; import { EditorOptions } from 'vs/workbench/common/editor'; import { ActionBar } from 'vs/base/browser/ui/actionbar/actionbar'; @@ -43,13 +43,13 @@ import { Color } from 'vs/base/common/color'; import { assign } from 'vs/base/common/objects'; import { INotificationService } from 'vs/platform/notification/common/notification'; import { CancellationToken } from 'vs/base/common/cancellation'; -import { ExtensionsTree, IExtensionData } from 'vs/workbench/contrib/extensions/browser/extensionsViewer'; +import { ExtensionsTree, ExtensionData } from 'vs/workbench/contrib/extensions/browser/extensionsViewer'; import { ShowCurrentReleaseNotesAction } from 'vs/workbench/contrib/update/electron-browser/update'; import { KeybindingParser } from 'vs/base/common/keybindingParser'; import { IStorageService } from 'vs/platform/storage/common/storage'; import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions'; import { getDefaultValue } from 'vs/platform/configuration/common/configurationRegistry'; -import { isUndefined, withUndefinedAsNull } from 'vs/base/common/types'; +import { isUndefined } from 'vs/base/common/types'; import { IWorkbenchThemeService } from 'vs/workbench/services/themes/common/workbenchThemeService'; function renderBody(body: string): string { @@ -177,7 +177,6 @@ export class ExtensionEditor extends BaseEditor { private extensionReadme: Cache | null; private extensionChangelog: Cache | null; private extensionManifest: Cache | null; - private extensionDependencies: Cache | null; private layoutParticipants: ILayoutParticipant[] = []; private contentDisposables: IDisposable[] = []; @@ -206,7 +205,6 @@ export class ExtensionEditor extends BaseEditor { this.extensionReadme = null; this.extensionChangelog = null; this.extensionManifest = null; - this.extensionDependencies = null; } createEditor(parent: HTMLElement): void { @@ -294,7 +292,6 @@ export class ExtensionEditor extends BaseEditor { this.extensionReadme = new Cache(() => createCancelablePromise(token => extension.getReadme(token))); this.extensionChangelog = new Cache(() => createCancelablePromise(token => extension.getChangelog(token))); this.extensionManifest = new Cache(() => createCancelablePromise(token => extension.getManifest(token))); - this.extensionDependencies = new Cache(() => createCancelablePromise(token => this.extensionsWorkbenchService.loadDependencies(extension, token))); const remoteBadge = this.instantiationService.createInstance(RemoteBadgeWidget, this.iconContainer, true); const onError = Event.once(domEvent(this.icon, 'error')); @@ -626,69 +623,28 @@ export class ExtensionEditor extends BaseEditor { } private openDependencies(extension: IExtension): Promise { - if (extension.dependencies.length === 0) { + if (arrays.isFalsyOrEmpty(extension.dependencies)) { append(this.content, $('p.nocontent')).textContent = localize('noDependencies', "No Dependencies"); return Promise.resolve(this.content); } - return this.loadContents(() => this.extensionDependencies!.get()) - .then(extensionDependencies => { - if (extensionDependencies) { - const content = $('div', { class: 'subcontent' }); - const scrollableContent = new DomScrollableElement(content, {}); - append(this.content, scrollableContent.getDomNode()); - this.contentDisposables.push(scrollableContent); + const content = $('div', { class: 'subcontent' }); + const scrollableContent = new DomScrollableElement(content, {}); + append(this.content, scrollableContent.getDomNode()); + this.contentDisposables.push(scrollableContent); - const dependenciesTree = this.renderDependencies(content, extensionDependencies); - const layout = () => { - scrollableContent.scanDomNode(); - const scrollDimensions = scrollableContent.getScrollDimensions(); - dependenciesTree.layout(scrollDimensions.height); - }; - const removeLayoutParticipant = arrays.insert(this.layoutParticipants, { layout }); - this.contentDisposables.push(toDisposable(removeLayoutParticipant)); + const dependenciesTree = this.instantiationService.createInstance(ExtensionsTree, new ExtensionData(extension, null, extension => extension.dependencies || [], this.extensionsWorkbenchService), content); + const layout = () => { + scrollableContent.scanDomNode(); + const scrollDimensions = scrollableContent.getScrollDimensions(); + dependenciesTree.layout(scrollDimensions.height); + }; + const removeLayoutParticipant = arrays.insert(this.layoutParticipants, { layout }); + this.contentDisposables.push(toDisposable(removeLayoutParticipant)); - this.contentDisposables.push(dependenciesTree); - scrollableContent.scanDomNode(); - return { focus() { dependenciesTree.domFocus(); } }; - } else { - append(this.content, $('p.nocontent')).textContent = localize('noDependencies', "No Dependencies"); - return Promise.resolve(this.content); - } - }, error => { - append(this.content, $('p.nocontent')).textContent = error; - this.notificationService.error(error); - return this.content; - }); - } - - private renderDependencies(container: HTMLElement, extensionDependencies: IExtensionDependencies): ExtensionsTree { - class ExtensionData implements IExtensionData { - - private readonly extensionDependencies: IExtensionDependencies; - - constructor(extensionDependencies: IExtensionDependencies) { - this.extensionDependencies = extensionDependencies; - } - - get extension(): IExtension { - return this.extensionDependencies.extension; - } - - get parent(): IExtensionData | null { - return this.extensionDependencies.dependent ? new ExtensionData(this.extensionDependencies.dependent) : null; - } - - get hasChildren(): boolean { - return this.extensionDependencies.hasDependencies; - } - - getChildren(): Promise { - return this.extensionDependencies.dependencies ? Promise.resolve(this.extensionDependencies.dependencies.map(d => new ExtensionData(d))) : Promise.resolve(null); - } - } - - return this.instantiationService.createInstance(ExtensionsTree, new ExtensionData(extensionDependencies), container); + this.contentDisposables.push(dependenciesTree); + scrollableContent.scanDomNode(); + return Promise.resolve({ focus() { dependenciesTree.domFocus(); } }); } private openExtensionPack(extension: IExtension): Promise { @@ -697,7 +653,7 @@ export class ExtensionEditor extends BaseEditor { append(this.content, scrollableContent.getDomNode()); this.contentDisposables.push(scrollableContent); - const extensionsPackTree = this.renderExtensionPack(content, extension); + const extensionsPackTree = this.instantiationService.createInstance(ExtensionsTree, new ExtensionData(extension, null, extension => extension.extensionPack || [], this.extensionsWorkbenchService), content); const layout = () => { scrollableContent.scanDomNode(); const scrollDimensions = scrollableContent.getScrollDimensions(); @@ -711,35 +667,6 @@ export class ExtensionEditor extends BaseEditor { return Promise.resolve({ focus() { extensionsPackTree.domFocus(); } }); } - private renderExtensionPack(container: HTMLElement, extension: IExtension): ExtensionsTree { - const extensionsWorkbenchService = this.extensionsWorkbenchService; - class ExtensionData implements IExtensionData { - - readonly extension: IExtension; - readonly parent: IExtensionData | null; - - constructor(extension: IExtension, parent?: IExtensionData) { - this.extension = extension; - this.parent = withUndefinedAsNull(parent); - } - - get hasChildren(): boolean { - return this.extension.extensionPack.length > 0; - } - - getChildren(): Promise { - if (this.hasChildren) { - const names = arrays.distinct(this.extension.extensionPack, e => e.toLowerCase()); - return extensionsWorkbenchService.queryGallery({ names, pageSize: names.length }, CancellationToken.None) - .then(result => result.firstPage.map(extension => new ExtensionData(extension, this))); - } - return Promise.resolve(null); - } - } - - return this.instantiationService.createInstance(ExtensionsTree, new ExtensionData(extension), container); - } - private renderSettings(container: HTMLElement, manifest: IExtensionManifest, onDetailsToggle: Function): boolean { const contributes = manifest.contributes; const configuration = contributes && contributes.configuration; diff --git a/src/vs/workbench/contrib/extensions/node/extensionsWorkbenchService.ts b/src/vs/workbench/contrib/extensions/node/extensionsWorkbenchService.ts index 25c72b03649..021dfe442f4 100644 --- a/src/vs/workbench/contrib/extensions/node/extensionsWorkbenchService.ts +++ b/src/vs/workbench/contrib/extensions/node/extensionsWorkbenchService.ts @@ -22,7 +22,7 @@ import { IConfigurationService } from 'vs/platform/configuration/common/configur import { IWindowService } from 'vs/platform/windows/common/windows'; import Severity from 'vs/base/common/severity'; import { URI } from 'vs/base/common/uri'; -import { IExtension, IExtensionDependencies, ExtensionState, IExtensionsWorkbenchService, AutoUpdateConfigurationKey, AutoCheckUpdatesConfigurationKey } from 'vs/workbench/contrib/extensions/common/extensions'; +import { IExtension, ExtensionState, IExtensionsWorkbenchService, AutoUpdateConfigurationKey, AutoCheckUpdatesConfigurationKey } from 'vs/workbench/contrib/extensions/common/extensions'; import { IEditorService, SIDE_GROUP, ACTIVE_GROUP } from 'vs/workbench/services/editor/common/editorService'; import { IURLService, IURLHandler } from 'vs/platform/url/common/url'; import { ExtensionsInput } from 'vs/workbench/contrib/extensions/common/extensionsInput'; @@ -303,53 +303,6 @@ ${this.description} } } -class ExtensionDependencies implements IExtensionDependencies { - - private _hasDependencies: boolean | null = null; - - constructor(private _extension: IExtension, private _identifier: string, private _map: Map, private _dependent: IExtensionDependencies | null = null) { } - - get hasDependencies(): boolean { - if (this._hasDependencies === null) { - this._hasDependencies = this.computeHasDependencies(); - } - return this._hasDependencies; - } - - get extension(): IExtension { - return this._extension; - } - - get identifier(): string { - return this._identifier; - } - - get dependent(): IExtensionDependencies | null { - return this._dependent; - } - - get dependencies(): IExtensionDependencies[] { - if (!this.hasDependencies) { - return []; - } - return this._extension.dependencies.map(id => new ExtensionDependencies(this._map.get(id)!, id, this._map, this)); - } - - private computeHasDependencies(): boolean { - if (this._extension && this._extension.dependencies.length > 0) { - let dependent = this._dependent; - while (dependent !== null) { - if (dependent.identifier === this.identifier) { - return false; - } - dependent = dependent.dependent; - } - return true; - } - return false; - } -} - class Extensions extends Disposable { private readonly _onChange: Emitter = new Emitter(); @@ -645,27 +598,6 @@ export class ExtensionsWorkbenchService extends Disposable implements IExtension }); } - loadDependencies(extension: IExtension, token: CancellationToken): Promise { - if (!extension.dependencies.length) { - return Promise.resolve(null); - } - - return this.extensionService.getExtensionsReport() - .then(report => { - const maliciousSet = getMaliciousExtensionsSet(report); - - return this.galleryService.loadAllDependencies((extension).dependencies.map(id => ({ id })), token) - .then(galleryExtensions => { - const extensions: IExtension[] = [...this.local, ...galleryExtensions.map(galleryExtension => this.fromGallery(galleryExtension, maliciousSet))]; - const map = new Map(); - for (const extension of extensions) { - map.set(extension.identifier.id, extension); - } - return new ExtensionDependencies(extension, extension.identifier.id, map); - }); - }); - } - open(extension: IExtension, sideByside: boolean = false): Promise { return Promise.resolve(this.editorService.openEditor(this.instantiationService.createInstance(ExtensionsInput, extension), undefined, sideByside ? SIDE_GROUP : ACTIVE_GROUP)); } diff --git a/src/vs/workbench/contrib/extensions/test/electron-browser/extensionsWorkbenchService.test.ts b/src/vs/workbench/contrib/extensions/test/electron-browser/extensionsWorkbenchService.test.ts index 2255fb50001..e5c1375072e 100644 --- a/src/vs/workbench/contrib/extensions/test/electron-browser/extensionsWorkbenchService.test.ts +++ b/src/vs/workbench/contrib/extensions/test/electron-browser/extensionsWorkbenchService.test.ts @@ -480,248 +480,6 @@ suite('ExtensionsWorkbenchServiceTest', () => { assert.ok(target.calledOnce); }); - test('test extension dependencies when empty', async () => { - testObject = await aWorkbenchService(); - instantiationService.stubPromise(IExtensionGalleryService, 'query', aPage(aGalleryExtension('a'))); - - return testObject.queryGallery(CancellationToken.None).then(page => { - return testObject.loadDependencies(page.firstPage[0], CancellationToken.None).then(dependencies => { - assert.equal(null, dependencies); - }); - }); - }); - - test('test one level extension dependencies without cycle', async () => { - testObject = await aWorkbenchService(); - instantiationService.stubPromise(IExtensionGalleryService, 'query', aPage(aGalleryExtension('a', {}, { dependencies: ['pub.b', 'pub.c', 'pub.d'] }))); - instantiationService.stubPromise(IExtensionGalleryService, 'loadAllDependencies', [aGalleryExtension('b'), aGalleryExtension('c'), aGalleryExtension('d')]); - - return testObject.queryGallery(CancellationToken.None).then(page => { - const extension = page.firstPage[0]; - return testObject.loadDependencies(extension, CancellationToken.None).then(actual => { - assert.ok(actual!.hasDependencies); - assert.equal(extension, actual!.extension); - assert.equal(null, actual!.dependent); - assert.equal(3, actual!.dependencies.length); - assert.equal('pub.a', actual!.identifier); - let dependent = actual; - - actual = dependent!.dependencies[0]; - assert.ok(!actual.hasDependencies); - assert.equal('pub.b', actual.extension.identifier.id); - assert.equal('pub.b', actual.identifier); - assert.equal(dependent, actual.dependent); - assert.equal(0, actual.dependencies.length); - - actual = dependent!.dependencies[1]; - assert.ok(!actual.hasDependencies); - assert.equal('pub.c', actual.extension.identifier.id); - assert.equal('pub.c', actual.identifier); - assert.equal(dependent, actual.dependent); - assert.equal(0, actual.dependencies.length); - - actual = dependent!.dependencies[2]; - assert.ok(!actual.hasDependencies); - assert.equal('pub.d', actual.extension.identifier.id); - assert.equal('pub.d', actual.identifier); - assert.equal(dependent, actual.dependent); - assert.equal(0, actual.dependencies.length); - }); - }); - }); - - test('test one level extension dependencies with cycle', async () => { - testObject = await aWorkbenchService(); - instantiationService.stubPromise(IExtensionGalleryService, 'query', aPage(aGalleryExtension('a', {}, { dependencies: ['pub.b', 'pub.a'] }))); - instantiationService.stubPromise(IExtensionGalleryService, 'loadAllDependencies', [aGalleryExtension('b'), aGalleryExtension('a')]); - - return testObject.queryGallery(CancellationToken.None).then(page => { - const extension = page.firstPage[0]; - return testObject.loadDependencies(extension, CancellationToken.None).then(actual => { - assert.ok(actual!.hasDependencies); - assert.equal(extension, actual!.extension); - assert.equal(null, actual!.dependent); - assert.equal(2, actual!.dependencies.length); - assert.equal('pub.a', actual!.identifier); - let dependent = actual; - - actual = dependent!.dependencies[0]!; - assert.ok(!actual.hasDependencies); - assert.equal('pub.b', actual.extension.identifier.id); - assert.equal('pub.b', actual.identifier); - assert.equal(dependent, actual.dependent); - assert.equal(0, actual.dependencies.length); - - actual = dependent!.dependencies[1]!; - assert.ok(!actual.hasDependencies); - assert.equal('pub.a', actual.extension.identifier.id); - assert.equal('pub.a', actual.identifier); - assert.equal(dependent, actual.dependent); - assert.equal(0, actual.dependencies.length); - }); - }); - }); - - test('test one level extension dependencies with missing dependencies', async () => { - testObject = await aWorkbenchService(); - instantiationService.stubPromise(IExtensionGalleryService, 'query', aPage(aGalleryExtension('a', {}, { dependencies: ['pub.b', 'pub.a'] }))); - instantiationService.stubPromise(IExtensionGalleryService, 'loadAllDependencies', [aGalleryExtension('a')]); - - return testObject.queryGallery(CancellationToken.None).then(page => { - const extension = page.firstPage[0]; - return testObject.loadDependencies(extension, CancellationToken.None).then(actual => { - assert.ok(actual!.hasDependencies); - assert.equal(extension, actual!.extension); - assert.equal(null, actual!.dependent); - assert.equal(2, actual!.dependencies.length); - assert.equal('pub.a', actual!.identifier); - let dependent = actual; - - actual = dependent!.dependencies[0]!; - assert.ok(!actual.hasDependencies); - assert.equal(null, actual.extension); - assert.equal('pub.b', actual.identifier); - assert.equal(dependent, actual.dependent); - assert.equal(0, actual.dependencies.length); - - actual = dependent!.dependencies[1]!; - assert.ok(!actual.hasDependencies); - assert.equal('pub.a', actual.extension.identifier.id); - assert.equal('pub.a', actual.identifier); - assert.equal(dependent, actual.dependent); - assert.equal(0, actual.dependencies.length); - }); - }); - }); - - test('test one level extension dependencies with in built dependencies', async () => { - const local = aLocalExtension('inbuilt', {}, { type: ExtensionType.System }); - instantiationService.stubPromise(IExtensionManagementService, 'getInstalled', [local]); - testObject = await aWorkbenchService(); - instantiationService.stubPromise(IExtensionGalleryService, 'query', aPage(aGalleryExtension('a', {}, { dependencies: ['pub.inbuilt', 'pub.a'] }))); - instantiationService.stubPromise(IExtensionGalleryService, 'loadAllDependencies', [aGalleryExtension('a')]); - - return testObject.queryGallery(CancellationToken.None).then(page => { - const extension = page.firstPage[0]; - return testObject.loadDependencies(extension, CancellationToken.None).then(actual => { - assert.ok(actual!.hasDependencies); - assert.equal(extension, actual!.extension); - assert.equal(null, actual!.dependent); - assert.equal(2, actual!.dependencies.length); - assert.equal('pub.a', actual!.identifier); - let dependent = actual; - - actual = dependent!.dependencies[0]!; - assert.ok(!actual.hasDependencies); - assert.equal('pub.inbuilt', actual.extension.identifier.id); - assert.equal('pub.inbuilt', actual.identifier); - assert.equal(dependent, actual.dependent); - assert.equal(0, actual.dependencies.length); - - - actual = dependent!.dependencies[1]!; - assert.ok(!actual.hasDependencies); - assert.equal('pub.a', actual.extension.identifier.id); - assert.equal('pub.a', actual.identifier); - assert.equal(dependent, actual.dependent); - assert.equal(0, actual.dependencies.length); - }); - }); - }); - - test('test more than one level of extension dependencies', async () => { - const local = aLocalExtension('c', { extensionDependencies: ['pub.d'] }, { type: ExtensionType.System }); - instantiationService.stubPromise(IExtensionManagementService, 'getInstalled', [local]); - testObject = await aWorkbenchService(); - instantiationService.stubPromise(IExtensionGalleryService, 'query', aPage(aGalleryExtension('a', {}, { dependencies: ['pub.b', 'pub.c'] }))); - instantiationService.stubPromise(IExtensionGalleryService, 'loadAllDependencies', [ - aGalleryExtension('b', {}, { dependencies: ['pub.d', 'pub.e'] }), - aGalleryExtension('d', {}, { dependencies: ['pub.f', 'pub.c'] }), - aGalleryExtension('e')]); - - return testObject.queryGallery(CancellationToken.None).then(page => { - const extension = page.firstPage[0]; - return testObject.loadDependencies(extension, CancellationToken.None).then(a => { - assert.ok(a!.hasDependencies); - assert.equal(extension, a!.extension); - assert.equal(null, a!.dependent); - assert.equal(2, a!.dependencies.length); - assert.equal('pub.a', a!.identifier); - - let b = a!.dependencies[0]; - assert.ok(b.hasDependencies); - assert.equal('pub.b', b.extension.identifier.id); - assert.equal('pub.b', b.identifier); - assert.equal(a, b.dependent); - assert.equal(2, b.dependencies.length); - - let c = a!.dependencies[1]; - assert.ok(c.hasDependencies); - assert.equal('pub.c', c.extension.identifier.id); - assert.equal('pub.c', c.identifier); - assert.equal(a, c.dependent); - assert.equal(1, c.dependencies.length); - - let d = b.dependencies[0]; - assert.ok(d.hasDependencies); - assert.equal('pub.d', d.extension.identifier.id); - assert.equal('pub.d', d.identifier); - assert.equal(b, d.dependent); - assert.equal(2, d.dependencies.length); - - let e = b.dependencies[1]; - assert.ok(!e.hasDependencies); - assert.equal('pub.e', e.extension.identifier.id); - assert.equal('pub.e', e.identifier); - assert.equal(b, e.dependent); - assert.equal(0, e.dependencies.length); - - let f = d.dependencies[0]; - assert.ok(!f.hasDependencies); - assert.equal(null, f.extension); - assert.equal('pub.f', f.identifier); - assert.equal(d, f.dependent); - assert.equal(0, f.dependencies.length); - - c = d.dependencies[1]; - assert.ok(c.hasDependencies); - assert.equal('pub.c', c.extension.identifier.id); - assert.equal('pub.c', c.identifier); - assert.equal(d, c.dependent); - assert.equal(1, c.dependencies.length); - - d = c.dependencies[0]; - assert.ok(!d.hasDependencies); - assert.equal('pub.d', d.extension.identifier.id); - assert.equal('pub.d', d.identifier); - assert.equal(c, d.dependent); - assert.equal(0, d.dependencies.length); - - c = a!.dependencies[1]; - d = c.dependencies[0]; - assert.ok(d.hasDependencies); - assert.equal('pub.d', d.extension.identifier.id); - assert.equal('pub.d', d.identifier); - assert.equal(c, d.dependent); - assert.equal(2, d.dependencies.length); - - f = d.dependencies[0]; - assert.ok(!f.hasDependencies); - assert.equal(null, f.extension); - assert.equal('pub.f', f.identifier); - assert.equal(d, f.dependent); - assert.equal(0, f.dependencies.length); - - c = d.dependencies[1]; - assert.ok(!c.hasDependencies); - assert.equal('pub.c', c.extension.identifier.id); - assert.equal('pub.c', c.identifier); - assert.equal(d, c.dependent); - assert.equal(0, c.dependencies.length); - }); - }); - }); - test('test uninstalled extensions are always enabled', async () => { return instantiationService.get(IExtensionEnablementService).setEnablement([aLocalExtension('b')], EnablementState.Disabled) .then(() => instantiationService.get(IExtensionEnablementService).setEnablement([aLocalExtension('c')], EnablementState.WorkspaceDisabled))