diff --git a/src/vs/workbench/parts/extensions/electron-browser/extensionsActions.ts b/src/vs/workbench/parts/extensions/electron-browser/extensionsActions.ts index 0d62b580bc5bc29506d27b6f6f974d9998f9a2b7..e1e6a53162cb72ec1855df630ad709ef513436e3 100644 --- a/src/vs/workbench/parts/extensions/electron-browser/extensionsActions.ts +++ b/src/vs/workbench/parts/extensions/electron-browser/extensionsActions.ts @@ -60,8 +60,8 @@ import { IDialogService } from 'vs/platform/dialogs/common/dialogs'; import { isUndefinedOrNull } from 'vs/base/common/types'; import { coalesce } from 'vs/base/common/arrays'; -const promptDownloadManually = (extension: IGalleryExtension, message: string, error: Error, instantiationService: IInstantiationService, notificationService: INotificationService, openerService: IOpenerService) => { - if (error.name === INSTALL_ERROR_INCOMPATIBLE || error.name === INSTALL_ERROR_MALICIOUS) { +const promptDownloadManually = (extension: IGalleryExtension | undefined, message: string, error: Error, instantiationService: IInstantiationService, notificationService: INotificationService, openerService: IOpenerService) => { + if (!extension || error.name === INSTALL_ERROR_INCOMPATIBLE || error.name === INSTALL_ERROR_MALICIOUS) { return Promise.reject(error); } else { const downloadUrl = `${product.extensionsGallery.serviceUrl}/publishers/${extension.publisher}/vsextensions/${extension.name}/${extension.version}/vspackage`; @@ -516,15 +516,17 @@ export class DropDownMenuActionItem extends ExtensionActionItem { } public showMenu(menuActionGroups: IAction[][], disposeActionsOnHide: boolean): void { - const actions = this.getActions(menuActionGroups); - let elementPosition = DOM.getDomNodePagePosition(this.element); - const anchor = { x: elementPosition.left, y: elementPosition.top + elementPosition.height + 10 }; - this.contextMenuService.showContextMenu({ - getAnchor: () => anchor, - getActions: () => actions, - actionRunner: this.actionRunner, - onHide: () => { if (disposeActionsOnHide) { dispose(actions); } } - }); + if (this.element) { + const actions = this.getActions(menuActionGroups); + let elementPosition = DOM.getDomNodePagePosition(this.element); + const anchor = { x: elementPosition.left, y: elementPosition.top + elementPosition.height + 10 }; + this.contextMenuService.showContextMenu({ + getAnchor: () => anchor, + getActions: () => actions, + actionRunner: this.actionRunner, + onHide: () => { if (disposeActionsOnHide) { dispose(actions); } } + }); + } } private getActions(menuActionGroups: IAction[][]): IAction[] { @@ -629,6 +631,9 @@ export class InstallAnotherVersionAction extends Action { } run(): Promise { + if (!this.enabled) { + return Promise.resolve(); + } return this.quickInputService.pick(this.getVersionEntries(), { placeHolder: localize('selectVersion', "Select Version to Install"), matchOnDetail: true }) .then(pick => { if (pick) { @@ -652,8 +657,8 @@ export class InstallAnotherVersionAction extends Action { }); } - private getVersionEntries(): Promise<(IQuickPickItem & { latest: boolean })[]> { - return this.extensionGalleryService.getAllVersions(this.extension.gallery, true) + private getVersionEntries(): Promise<(IQuickPickItem & { latest: boolean, id: string })[]> { + return this.extensionGalleryService.getAllVersions(this.extension.gallery!, true) .then(allVersions => allVersions.map((v, i) => ({ id: v.version, label: v.version, description: `${getRelativeDateLabel(new Date(Date.parse(v.date)))}${v.version === this.extension.version ? ` (${localize('current', "Current")})` : ''}`, latest: i === 0 }))); } } @@ -749,7 +754,7 @@ export class EnableForWorkspaceAction extends Action implements IExtensionAction } this.enabled = false; if (this.extension) { - this.enabled = this.extension.state === ExtensionState.Installed && (this.extension.enablementState === EnablementState.Disabled || this.extension.enablementState === EnablementState.WorkspaceDisabled) && this.extension.local && this.extensionEnablementService.canChangeEnablement(this.extension.local); + this.enabled = this.extension.state === ExtensionState.Installed && (this.extension.enablementState === EnablementState.Disabled || this.extension.enablementState === EnablementState.WorkspaceDisabled) && !!this.extension.local && this.extensionEnablementService.canChangeEnablement(this.extension.local); } } @@ -796,7 +801,7 @@ export class InstallInRemoteServerAction extends Action implements IExtensionAct && this.extension.state === ExtensionState.Installed) { const installedInRemoteServer = this.extension.locals.some(local => { const server = this.extensionManagementServerService.getExtensionManagementServer(local.location); - return server && server.authority === this.extensionManagementServerService.remoteExtensionManagementServer.authority; + return !!server && server.authority === this.extensionManagementServerService.remoteExtensionManagementServer!.authority; }); if (!installedInRemoteServer) { this.enabled = !this.runningExtensions.some(e => areSameExtensions({ id: e.id }, { id: this.extension.id })); @@ -809,7 +814,7 @@ export class InstallInRemoteServerAction extends Action implements IExtensionAct return Promise.resolve(); } if (this.storageService.getBoolean('askToInstallRemoteServerExtension', StorageScope.GLOBAL, true)) { - const message = localize('install extension', "Enabling the '{0}' extension will also install it in {1}. Would you like to continue?", this.extension.displayName, this.labelService.getHostLabel() || this.extensionManagementServerService.remoteExtensionManagementServer.authority); + const message = localize('install extension', "Enabling the '{0}' extension will also install it in {1}. Would you like to continue?", this.extension.displayName, this.labelService.getHostLabel() || this.extensionManagementServerService.remoteExtensionManagementServer!.authority); const response = await this.dialogService.confirm({ type: 'info', message, checkbox: { label: localize('do not ask me again', "Do not ask me again") } }); if (!response || !response.confirmed) { return Promise.resolve(); @@ -818,12 +823,12 @@ export class InstallInRemoteServerAction extends Action implements IExtensionAct this.storageService.store('askToInstallRemoteServerExtension', false, StorageScope.GLOBAL); } } - const galleryExtension = this.extension.gallery ? this.extension.gallery : await this.extensionGalleryService.getExtension(this.extension.local.galleryIdentifier); + const galleryExtension = this.extension.gallery ? this.extension.gallery : await this.extensionGalleryService.getExtension(this.extension.local!.galleryIdentifier); if (galleryExtension) { - return this.extensionManagementServerService.remoteExtensionManagementServer.extensionManagementService.installFromGallery(galleryExtension); + return this.extensionManagementServerService.remoteExtensionManagementServer!.extensionManagementService.installFromGallery(galleryExtension); } else { - const zipLocation = await this.extensionManagementServerService.localExtensionManagementServer.extensionManagementService.zip(this.extension.local); - return this.extensionManagementServerService.remoteExtensionManagementServer.extensionManagementService.unzip(zipLocation, this.extension.type); + const zipLocation = await this.extensionManagementServerService.localExtensionManagementServer.extensionManagementService.zip(this.extension.local!); + return this.extensionManagementServerService.remoteExtensionManagementServer!.extensionManagementService.unzip(zipLocation, this.extension.type!); } } @@ -860,7 +865,7 @@ export class EnableGloballyAction extends Action implements IExtensionAction { if (!isUIExtension(this.extension.local.manifest, this.configurationService) && this.extensionManagementServerService.remoteExtensionManagementServer) { if (!this.extension.locals.some(local => { const server = this.extensionManagementServerService.getExtensionManagementServer(local.location); - return server && server.authority === this.extensionManagementServerService.remoteExtensionManagementServer.authority; + return !!server && server.authority === this.extensionManagementServerService.remoteExtensionManagementServer!.authority; })) { return; } @@ -902,7 +907,7 @@ export class DisableForWorkspaceAction extends Action implements IExtensionActio } this.enabled = false; if (this.extension && this.runningExtensions.some(e => areSameExtensions({ id: e.id }, { id: this.extension.id }) && this.workspaceContextService.getWorkbenchState() !== WorkbenchState.EMPTY)) { - this.enabled = this.extension.state === ExtensionState.Installed && (this.extension.enablementState === EnablementState.Enabled || this.extension.enablementState === EnablementState.WorkspaceEnabled) && this.extension.local && this.extensionEnablementService.canChangeEnablement(this.extension.local); + this.enabled = this.extension.state === ExtensionState.Installed && (this.extension.enablementState === EnablementState.Enabled || this.extension.enablementState === EnablementState.WorkspaceEnabled) && !!this.extension.local && this.extensionEnablementService.canChangeEnablement(this.extension.local); } } @@ -938,7 +943,7 @@ export class DisableGloballyAction extends Action implements IExtensionAction { } this.enabled = false; if (this.extension && this.runningExtensions.some(e => areSameExtensions({ id: e.id }, { id: this.extension.id }))) { - this.enabled = this.extension.state === ExtensionState.Installed && (this.extension.enablementState === EnablementState.Enabled || this.extension.enablementState === EnablementState.WorkspaceEnabled) && this.extension.local && this.extensionEnablementService.canChangeEnablement(this.extension.local); + this.enabled = this.extension.state === ExtensionState.Installed && (this.extension.enablementState === EnablementState.Enabled || this.extension.enablementState === EnablementState.WorkspaceEnabled) && !!this.extension.local && this.extensionEnablementService.canChangeEnablement(this.extension.local); } } @@ -1220,16 +1225,16 @@ export class ReloadAction extends Action { this.enabled = false; this.tooltip = ''; if (!this.extension) { - return Promise.resolve(null); + return Promise.resolve(); } const state = this.extension.state; if (state === ExtensionState.Installing || state === ExtensionState.Uninstalling) { - return Promise.resolve(null); + return Promise.resolve(); } const installed = this.extensionsWorkbenchService.local.filter(e => e.id === this.extension.id)[0]; const local = this.extension.local || (installed && installed.local); if (local && local.manifest && local.manifest.contributes && local.manifest.contributes.localizations && local.manifest.contributes.localizations.length > 0) { - return Promise.resolve(null); + return Promise.resolve(); } return this.extensionService.getExtensions() .then(runningExtensions => this.computeReloadState(runningExtensions, installed)); @@ -1264,12 +1269,18 @@ export class ReloadAction extends Action { const uiExtension = isUIExtension(installed.local.manifest, this.configurationService); if (!isDisabled) { let enableReload = true; - if (this.extensionManagementServerService.remoteExtensionManagementServer) { + if (this.extensionManagementServerService.remoteExtensionManagementServer && installed.locals) { if (uiExtension) { // Only UI extension from local server requires reload if it is not running on the server - enableReload = installed.locals.some(local => this.extensionManagementServerService.getExtensionManagementServer(local.location).authority === this.extensionManagementServerService.localExtensionManagementServer.authority); + enableReload = installed.locals.some(local => { + const server = this.extensionManagementServerService.getExtensionManagementServer(local.location); + return !!server && server.authority === this.extensionManagementServerService.localExtensionManagementServer.authority; + }); } else { - enableReload = installed.locals.some(local => this.extensionManagementServerService.getExtensionManagementServer(local.location).authority === this.extensionManagementServerService.remoteExtensionManagementServer.authority); + enableReload = installed.locals.some(local => { + const server = this.extensionManagementServerService.getExtensionManagementServer(local.location); + return !!server && server.authority === this.extensionManagementServerService.remoteExtensionManagementServer!.authority; + }); } } @@ -1331,7 +1342,7 @@ export class ShowEnabledExtensionsAction extends Action { label: string, @IViewletService private viewletService: IViewletService ) { - super(id, label, null, true); + super(id, label, void 0, true); } run(): Promise { @@ -1354,7 +1365,7 @@ export class ShowInstalledExtensionsAction extends Action { label: string, @IViewletService private viewletService: IViewletService ) { - super(id, label, null, true); + super(id, label, void 0, true); } run(): Promise { @@ -1436,7 +1447,7 @@ export class ShowBuiltInExtensionsAction extends Action { label: string, @IViewletService private viewletService: IViewletService ) { - super(id, label, null, true); + super(id, label, void 0, true); } run(): Promise { @@ -1459,7 +1470,7 @@ export class ShowOutdatedExtensionsAction extends Action { label: string, @IViewletService private viewletService: IViewletService ) { - super(id, label, null, true); + super(id, label, void 0, true); } run(): Promise { @@ -1482,7 +1493,7 @@ export class ShowPopularExtensionsAction extends Action { label: string, @IViewletService private viewletService: IViewletService ) { - super(id, label, null, true); + super(id, label, void 0, true); } run(): Promise { @@ -1505,7 +1516,7 @@ export class ShowRecommendedExtensionsAction extends Action { label: string, @IViewletService private viewletService: IViewletService ) { - super(id, label, null, true); + super(id, label, void 0, true); } run(): Promise { @@ -1580,7 +1591,7 @@ export class InstallRecommendedExtensionAction extends Action { @IOpenerService private openerService: IOpenerService, @IExtensionsWorkbenchService private extensionWorkbenchService: IExtensionsWorkbenchService ) { - super(InstallRecommendedExtensionAction.ID, InstallRecommendedExtensionAction.LABEL, null, false); + super(InstallRecommendedExtensionAction.ID, InstallRecommendedExtensionAction.LABEL, void 0, false); this.extensionId = extensionId; } @@ -1677,7 +1688,7 @@ export class ShowRecommendedKeymapExtensionsAction extends Action { label: string, @IViewletService private viewletService: IViewletService ) { - super(id, label, null, true); + super(id, label, void 0, true); } run(): Promise { @@ -1700,7 +1711,7 @@ export class ShowLanguageExtensionsAction extends Action { label: string, @IViewletService private viewletService: IViewletService ) { - super(id, label, null, true); + super(id, label, void 0, true); } run(): Promise { @@ -1723,7 +1734,7 @@ export class ShowAzureExtensionsAction extends Action { label: string, @IViewletService private viewletService: IViewletService ) { - super(id, label, null, true); + super(id, label, void 0, true); } run(): Promise { @@ -1748,7 +1759,7 @@ export class ChangeSortAction extends Action { private sortBy: string, @IViewletService private viewletService: IViewletService ) { - super(id, label, null, true); + super(id, label, void 0, true); if (sortBy === undefined) { throw new Error('bad arguments'); @@ -1762,7 +1773,7 @@ export class ChangeSortAction extends Action { private onSearchChange(value: string): void { const query = Query.parse(value); this.query = new Query(query.value, this.sortBy || query.sortBy, query.groupBy); - this.enabled = value && this.query.isValid() && !this.query.equals(query); + this.enabled = !!value && this.query.isValid() && !this.query.equals(query); } run(): Promise { @@ -1787,7 +1798,7 @@ export class ChangeGroupAction extends Action { private groupBy: string, @IViewletService private viewletService: IViewletService ) { - super(id, label, null, true); + super(id, label, void 0, true); if (groupBy === undefined) { throw new Error('bad arguments'); @@ -1936,7 +1947,7 @@ export abstract class AbstractConfigureRecommendedExtensionsAction extends Actio @IJSONEditingService private jsonEditingService: IJSONEditingService, @ITextModelService private textModelResolverService: ITextModelService ) { - super(id, label, null); + super(id, label); } protected openExtensionsFile(extensionsFileResource: URI): Promise { @@ -2006,7 +2017,7 @@ export abstract class AbstractConfigureRecommendedExtensionsAction extends Actio insertInto.push(extensionId); - let removeFromPromise = Promise.resolve(null); + let removeFromPromise: Promise = Promise.resolve(); if (removeFrom.some(e => e.toLowerCase() === extensionIdLowerCase)) { removeFrom = removeFrom.filter(x => x.toLowerCase() !== extensionIdLowerCase); removeFromPromise = this.jsonEditingService.write(extensionsFileResource, @@ -2057,7 +2068,7 @@ export abstract class AbstractConfigureRecommendedExtensionsAction extends Actio private getSelectionPosition(content: string, resource: URI, path: json.JSONPath): Promise { const tree = json.parseTree(content); const node = json.findNodeAtLocation(tree, path); - if (node && node.parent.children[1]) { + if (node && node.parent && node.parent.children) { const recommendationsValueNode = node.parent.children[1]; const lastExtensionNode = recommendationsValueNode.children && recommendationsValueNode.children.length ? recommendationsValueNode.children[recommendationsValueNode.children.length - 1] : null; const offset = lastExtensionNode ? lastExtensionNode.offset + lastExtensionNode.length : recommendationsValueNode.offset + 1; @@ -2073,7 +2084,7 @@ export abstract class AbstractConfigureRecommendedExtensionsAction extends Actio }; }); } - return Promise.resolve(null); + return Promise.resolve(); } private getOrCreateExtensionsFile(extensionsFileResource: URI): Promise<{ created: boolean, extensionsFileResource: URI, content: string }> { @@ -2112,14 +2123,14 @@ export class ConfigureWorkspaceRecommendedExtensionsAction extends AbstractConfi this.enabled = this.contextService.getWorkbenchState() !== WorkbenchState.EMPTY; } - public run(): Promise { + public run(): Promise { switch (this.contextService.getWorkbenchState()) { case WorkbenchState.FOLDER: return this.openExtensionsFile(this.contextService.getWorkspace().folders[0].toResource(paths.join('.vscode', 'extensions.json'))); case WorkbenchState.WORKSPACE: - return this.openWorkspaceConfigurationFile(this.contextService.getWorkspace().configuration); + return this.openWorkspaceConfigurationFile(this.contextService.getWorkspace().configuration!); } - return Promise.resolve(null); + return Promise.resolve(); } dispose(): void { @@ -2196,12 +2207,12 @@ export class AddToWorkspaceFolderRecommendationsAction extends AbstractConfigure run(shouldRecommend: boolean): Promise { if (!(this.editorService.activeEditor instanceof ExtensionsInput) || !this.editorService.activeEditor.extension) { - return Promise.resolve(null); + return Promise.resolve(); } const folders = this.contextService.getWorkspace().folders; if (!folders || !folders.length) { this.notificationService.info(localize('AddToWorkspaceFolderRecommendations.noWorkspace', 'There are no workspace folders open to add recommendations.')); - return Promise.resolve(null); + return Promise.resolve(); } const extensionId = this.editorService.activeEditor.extension.id; @@ -2211,7 +2222,7 @@ export class AddToWorkspaceFolderRecommendationsAction extends AbstractConfigure return Promise.resolve(pickFolderPromise) .then(workspaceFolder => { if (!workspaceFolder) { - return Promise.resolve(null); + return Promise.resolve(); } const configurationFile = workspaceFolder.toResource(paths.join('.vscode', 'extensions.json')); return this.getWorkspaceFolderExtensionsConfigContent(configurationFile).then(content => { @@ -2219,7 +2230,7 @@ export class AddToWorkspaceFolderRecommendationsAction extends AbstractConfigure if (shouldRecommend) { if ((content.recommendations || []).some(e => e.toLowerCase() === extensionIdLowerCase)) { this.notificationService.info(localize('AddToWorkspaceFolderRecommendations.alreadyExists', 'This extension is already present in this workspace folder\'s recommendations.')); - return Promise.resolve(null); + return Promise.resolve(); } return this.addExtensionToWorkspaceFolderConfig(configurationFile, extensionId, shouldRecommend).then(() => { @@ -2236,7 +2247,7 @@ export class AddToWorkspaceFolderRecommendationsAction extends AbstractConfigure else { if ((content.unwantedRecommendations || []).some(e => e.toLowerCase() === extensionIdLowerCase)) { this.notificationService.info(localize('AddToWorkspaceFolderIgnoredRecommendations.alreadyExists', 'This extension is already present in this workspace folder\'s unwanted recommendations.')); - return Promise.resolve(null); + return Promise.resolve(); } return this.addExtensionToWorkspaceFolderConfig(configurationFile, extensionId, shouldRecommend).then(() => { @@ -2277,11 +2288,12 @@ export class AddToWorkspaceRecommendationsAction extends AbstractConfigureRecomm } run(shouldRecommend: boolean): Promise { - if (!(this.editorService.activeEditor instanceof ExtensionsInput) || !this.editorService.activeEditor.extension) { - return Promise.resolve(null); - } const workspaceConfig = this.contextService.getWorkspace().configuration; + if (!(this.editorService.activeEditor instanceof ExtensionsInput) || !this.editorService.activeEditor.extension || !workspaceConfig) { + return Promise.resolve(); + } + const extensionId = this.editorService.activeEditor.extension.id; return this.getWorkspaceExtensionsConfigContent(workspaceConfig).then(content => { @@ -2289,7 +2301,7 @@ export class AddToWorkspaceRecommendationsAction extends AbstractConfigureRecomm if (shouldRecommend) { if ((content.recommendations || []).some(e => e.toLowerCase() === extensionIdLowerCase)) { this.notificationService.info(localize('AddToWorkspaceRecommendations.alreadyExists', 'This extension is already present in workspace recommendations.')); - return Promise.resolve(null); + return Promise.resolve(); } return this.addExtensionToWorkspaceConfig(workspaceConfig, extensionId, shouldRecommend).then(() => { @@ -2306,7 +2318,7 @@ export class AddToWorkspaceRecommendationsAction extends AbstractConfigureRecomm } else { if ((content.unwantedRecommendations || []).some(e => e.toLowerCase() === extensionIdLowerCase)) { this.notificationService.info(localize('AddToWorkspaceUnwantedRecommendations.alreadyExists', 'This extension is already present in workspace unwanted recommendations.')); - return Promise.resolve(null); + return Promise.resolve(); } return this.addExtensionToWorkspaceConfig(workspaceConfig, extensionId, shouldRecommend).then(() => { @@ -2381,10 +2393,10 @@ export class DisabledStatusLabelAction extends Action { this.class = `${DisabledStatusLabelAction.Class} hide`; this.tooltip = ''; if (this.extension && this.extension.local && !this.extension.isMalicious && !this.runningExtensions.some(e => e.id === this.extension.id)) { - if (this.extensionManagementServerService.remoteExtensionManagementServer && !isUIExtension(this.extension.local.manifest, this.configurationService)) { + if (this.extensionManagementServerService.remoteExtensionManagementServer && !isUIExtension(this.extension.local.manifest, this.configurationService) && this.extension.locals) { const installedInRemoteServer = this.extension.locals.some(local => { const server = this.extensionManagementServerService.getExtensionManagementServer(local.location); - return server && server.authority === this.extensionManagementServerService.remoteExtensionManagementServer.authority; + return !!server && server.authority === this.extensionManagementServerService.remoteExtensionManagementServer!.authority; }); if (!installedInRemoteServer) { this.class = `${DisabledStatusLabelAction.Class}`; @@ -2418,7 +2430,7 @@ export class DisableAllAction extends Action { } private update(): void { - this.enabled = this.extensionsWorkbenchService.local.some(e => e.type === LocalExtensionType.User && (e.enablementState === EnablementState.Enabled || e.enablementState === EnablementState.WorkspaceEnabled) && e.local && this.extensionEnablementService.canChangeEnablement(e.local)); + this.enabled = this.extensionsWorkbenchService.local.some(e => e.type === LocalExtensionType.User && (e.enablementState === EnablementState.Enabled || e.enablementState === EnablementState.WorkspaceEnabled) && !!e.local && this.extensionEnablementService.canChangeEnablement(e.local)); } run(): Promise { @@ -2481,7 +2493,7 @@ export class EnableAllAction extends Action { } private update(): void { - this.enabled = this.extensionsWorkbenchService.local.some(e => e.local && this.extensionEnablementService.canChangeEnablement(e.local) && (e.enablementState === EnablementState.Disabled || e.enablementState === EnablementState.WorkspaceDisabled)); + this.enabled = this.extensionsWorkbenchService.local.some(e => !!e.local && this.extensionEnablementService.canChangeEnablement(e.local) && (e.enablementState === EnablementState.Disabled || e.enablementState === EnablementState.WorkspaceDisabled)); } run(): Promise { @@ -2514,7 +2526,7 @@ export class EnableAllWorkpsaceAction extends Action { } private update(): void { - this.enabled = this.workspaceContextService.getWorkbenchState() !== WorkbenchState.EMPTY && this.extensionsWorkbenchService.local.some(e => e.local && this.extensionEnablementService.canChangeEnablement(e.local) && (e.enablementState === EnablementState.Disabled || e.enablementState === EnablementState.WorkspaceDisabled)); + this.enabled = this.workspaceContextService.getWorkbenchState() !== WorkbenchState.EMPTY && this.extensionsWorkbenchService.local.some(e => !!e.local && this.extensionEnablementService.canChangeEnablement(e.local) && (e.enablementState === EnablementState.Disabled || e.enablementState === EnablementState.WorkspaceDisabled)); } run(): Promise { @@ -2539,7 +2551,7 @@ export class OpenExtensionsFolderAction extends Action { @IFileService private fileService: IFileService, @IEnvironmentService private environmentService: IEnvironmentService ) { - super(id, label, null, true); + super(id, label, void 0, true); } run(): Promise { @@ -2688,22 +2700,22 @@ export class InstallSpecificVersionOfExtensionAction extends Action { const versionPick = await this.quickInputService.pick(extensionPick.versions.map(v => ({ id: v.version, label: v.version, description: `${getRelativeDateLabel(new Date(Date.parse(v.date)))}${v.version === extensionPick.extension.version ? ` (${localize('current', "Current")})` : ''}` })), { placeHolder: localize('selectVersion', "Select Version to Install"), matchOnDetail: true }); if (versionPick) { if (extensionPick.extension.version !== versionPick.id) { - await this.install(extensionPick.extension, versionPick.id === extensionPick.versions[0].version ? void 0 : versionPick.id); + await this.install(extensionPick.extension, versionPick.id); } } } } private isEnabled(extension: IExtension): boolean { - return extension.gallery && (extension.enablementState === EnablementState.Enabled || extension.enablementState === EnablementState.WorkspaceEnabled); + return !!extension.gallery && (extension.enablementState === EnablementState.Enabled || extension.enablementState === EnablementState.WorkspaceEnabled); } private async getExtensionEntries(): Promise<(IQuickPickItem & { extension: IExtension, versions: IGalleryExtensionVersion[] })[]> { const installed = await this.extensionsWorkbenchService.queryLocal(); - const versionsPromises: Promise<{ extension: IExtension, versions: IGalleryExtensionVersion[] }>[] = []; + const versionsPromises: Promise<{ extension: IExtension, versions: IGalleryExtensionVersion[] } | null>[] = []; for (const extension of installed) { if (this.isEnabled(extension)) { - versionsPromises.push(this.extensionGalleryService.getAllVersions(extension.gallery, true) + versionsPromises.push(this.extensionGalleryService.getAllVersions(extension.gallery!, true) .then(versions => (versions.length ? { extension, versions } : null))); } } diff --git a/src/vs/workbench/parts/extensions/node/extensionsWorkbenchService.ts b/src/vs/workbench/parts/extensions/node/extensionsWorkbenchService.ts index fb834e57a31de4a6c40fde2cb3c08d7dd121b01a..94bc7fad276b57983f34710c90dd8711b50d4768 100644 --- a/src/vs/workbench/parts/extensions/node/extensionsWorkbenchService.ts +++ b/src/vs/workbench/parts/extensions/node/extensionsWorkbenchService.ts @@ -726,7 +726,7 @@ export class ExtensionsWorkbenchService implements IExtensionsWorkbenchService, } if (!extension.gallery) { - return Promise.resolve(); + return Promise.reject(new Error('Missing gallery')); } return this.galleryService.getExtension(extension.gallery.identifier, version) @@ -736,7 +736,11 @@ export class ExtensionsWorkbenchService implements IExtensionsWorkbenchService, } return this.installWithProgress( () => this.extensionService.installFromGallery(gallery) - .then(() => this.ignoreAutoUpdate(gallery.identifier.id, version)) + .then(() => { + if (extension.latestVersion !== version) { + this.ignoreAutoUpdate(gallery.identifier.id, version); + } + }) , gallery.displayName); }); } @@ -919,8 +923,6 @@ export class ExtensionsWorkbenchService implements IExtensionsWorkbenchService, extension = new Extension(this.galleryService, this.stateProvider, [], gallery, this.telemetryService, this.logService); } - extension.gallery = gallery; - this.installing.push(extension); this._onChange.fire(extension);