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

reuse extension data for deps and pack tree.

上级 27819b39
......@@ -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<IExtensionData, IExte
}
}));
}
}
export class ExtensionData implements IExtensionData {
readonly extension: IExtension;
readonly parent: IExtensionData | null;
private readonly getChildrenExtensionIds: (extension: IExtension) => 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<IExtensionData[] | null> {
if (this.hasChildren) {
const localById = this.extensionsWorkbenchService.local.reduce((result, e) => { result.set(e.identifier.id.toLowerCase(), e); return result; }, new Map<string, IExtension>());
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
......@@ -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<IExtensionsWorkbenchService>(SERVICE_ID);
......@@ -95,7 +87,6 @@ export interface IExtensionsWorkbenchService {
installVersion(extension: IExtension, version: string): Promise<IExtension>;
reinstall(extension: IExtension): Promise<IExtension>;
setEnablement(extensions: IExtension | IExtension[], enablementState: EnablementState): Promise<void>;
loadDependencies(extension: IExtension, token: CancellationToken): Promise<IExtensionDependencies | null>;
open(extension: IExtension, sideByside?: boolean): Promise<any>;
checkForUpdates(): Promise<void>;
allowedBadgeProviders: string[];
......
......@@ -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<string> | null;
private extensionChangelog: Cache<string> | null;
private extensionManifest: Cache<IExtensionManifest | null> | null;
private extensionDependencies: Cache<IExtensionDependencies | null> | 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<IActiveElement> {
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<IActiveElement, IActiveElement>(extensionDependencies => {
if (extensionDependencies) {
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));
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;
}
const content = $('div', { class: 'subcontent' });
const scrollableContent = new DomScrollableElement(content, {});
append(this.content, scrollableContent.getDomNode());
this.contentDisposables.push(scrollableContent);
getChildren(): Promise<IExtensionData[] | null> {
return this.extensionDependencies.dependencies ? Promise.resolve(this.extensionDependencies.dependencies.map(d => new ExtensionData(d))) : Promise.resolve(null);
}
}
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));
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<IActiveElement> {
......@@ -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<IExtensionData[] | null> {
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;
......
......@@ -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<string, IExtension>, 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<Extension | undefined> = new Emitter<Extension | undefined>();
......@@ -645,27 +598,6 @@ export class ExtensionsWorkbenchService extends Disposable implements IExtension
});
}
loadDependencies(extension: IExtension, token: CancellationToken): Promise<IExtensionDependencies | null> {
if (!extension.dependencies.length) {
return Promise.resolve(null);
}
return this.extensionService.getExtensionsReport()
.then(report => {
const maliciousSet = getMaliciousExtensionsSet(report);
return this.galleryService.loadAllDependencies((<Extension>extension).dependencies.map(id => ({ id })), token)
.then(galleryExtensions => {
const extensions: IExtension[] = [...this.local, ...galleryExtensions.map(galleryExtension => this.fromGallery(galleryExtension, maliciousSet))];
const map = new Map<string, IExtension>();
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<any> {
return Promise.resolve(this.editorService.openEditor(this.instantiationService.createInstance(ExtensionsInput, extension), undefined, sideByside ? SIDE_GROUP : ACTIVE_GROUP));
}
......
......@@ -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))
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册