#14821 Move extension enablement closer to extension management

This commit is contained in:
Sandeep Somavarapu
2016-11-02 10:16:34 +01:00
parent ccfc178868
commit c5c0c39d9a
7 changed files with 84 additions and 89 deletions

View File

@@ -11,7 +11,8 @@ import { localize } from 'vs/nls';
import * as path from 'path';
import URI from 'vs/base/common/uri';
import { AbstractExtensionService, ActivatedExtension } from 'vs/platform/extensions/common/abstractExtensionService';
import { IExtensionRuntimeService, IMessage, IExtensionDescription, IExtensionsStatus } from 'vs/platform/extensions/common/extensions';
import { IMessage, IExtensionDescription, IExtensionsStatus } from 'vs/platform/extensions/common/extensions';
import { IExtensionEnablementService } from 'vs/platform/extensionManagement/common/extensionManagement';
import { ExtensionsRegistry, ExtensionPoint, IExtensionPointUser, ExtensionMessageCollector } from 'vs/platform/extensions/common/extensionsRegistry';
import { ExtensionScanner, MessagesCollector } from 'vs/workbench/node/extensionPoints';
import { IMessageService } from 'vs/platform/message/common/message';
@@ -61,7 +62,7 @@ export class MainProcessExtensionService extends AbstractExtensionService<Activa
@IThreadService threadService: IThreadService,
@IMessageService messageService: IMessageService,
@IEnvironmentService private environmentService: IEnvironmentService,
@IExtensionRuntimeService extensionsRuntimeService: IExtensionRuntimeService
@IExtensionEnablementService extensionEnablementService: IExtensionEnablementService
) {
super(false);
this._isDev = !environmentService.isBuilt || !!environmentService.extensionDevelopmentPath;
@@ -71,7 +72,7 @@ export class MainProcessExtensionService extends AbstractExtensionService<Activa
this._proxy = this._threadService.get(ExtHostContext.ExtHostExtensionService);
this._extensionsStatus = {};
const disabledExtensions = [...extensionsRuntimeService.getGloballyDisabledExtensions(), ...extensionsRuntimeService.getWorkspaceDisabledExtensions()];
const disabledExtensions = [...extensionEnablementService.getGloballyDisabledExtensions(), ...extensionEnablementService.getWorkspaceDisabledExtensions()];
this.scanExtensions().done(extensionDescriptions => {
this._onExtensionDescriptions(disabledExtensions.length ? extensionDescriptions.filter(e => disabledExtensions.indexOf(`${e.publisher}.${e.name}`) === -1) : extensionDescriptions);
});

View File

@@ -64,7 +64,7 @@ import { IThreadService } from 'vs/workbench/services/thread/common/threadServic
import { ICommandService } from 'vs/platform/commands/common/commands';
import { CommandService } from 'vs/platform/commands/common/commandService';
import { IWorkspaceContextService, IWorkspace } from 'vs/platform/workspace/common/workspace';
import { IExtensionService, IExtensionRuntimeService } from 'vs/platform/extensions/common/extensions';
import { IExtensionService } from 'vs/platform/extensions/common/extensions';
import { MainThreadModeServiceImpl } from 'vs/editor/common/services/modeServiceImpl';
import { IModeService } from 'vs/editor/common/services/modeService';
import { IUntitledEditorService, UntitledEditorService } from 'vs/workbench/services/untitled/common/untitledEditorService';
@@ -75,13 +75,13 @@ import { getDelayedChannel } from 'vs/base/parts/ipc/common/ipc';
import { connect as connectNet } from 'vs/base/parts/ipc/node/ipc.net';
import { Client as ElectronIPCClient } from 'vs/base/parts/ipc/electron-browser/ipc.electron-browser';
import { IExtensionManagementChannel, ExtensionManagementChannelClient } from 'vs/platform/extensionManagement/common/extensionManagementIpc';
import { IExtensionManagementService } from 'vs/platform/extensionManagement/common/extensionManagement';
import { IExtensionManagementService, IExtensionEnablementService } from 'vs/platform/extensionManagement/common/extensionManagement';
import { ExtensionEnablementService } from 'vs/platform/extensionManagement/common/extensionEnablementService';
import { URLChannelClient } from 'vs/platform/url/common/urlIpc';
import { IURLService } from 'vs/platform/url/common/url';
import { ReloadWindowAction } from 'vs/workbench/electron-browser/actions';
import { WorkspaceConfigurationService } from 'vs/workbench/services/configuration/node/configurationService';
import { ExtensionHostProcessWorker } from 'vs/workbench/electron-browser/extensionHost';
import { ExtensionRuntimeService } from 'vs/workbench/services/extensions/common/extensionRuntimeService';
import { remote } from 'electron';
// self registering services
@@ -292,9 +292,9 @@ export class WorkbenchShell {
const extensionManagementChannelClient = new ExtensionManagementChannelClient(extensionManagementChannel);
serviceCollection.set(IExtensionManagementService, extensionManagementChannelClient);
const extensionsRuntimeService = instantiationService.createInstance(ExtensionRuntimeService);
serviceCollection.set(IExtensionRuntimeService, extensionsRuntimeService);
disposables.add(extensionsRuntimeService);
const extensionEnablementService = instantiationService.createInstance(ExtensionEnablementService);
serviceCollection.set(IExtensionEnablementService, extensionEnablementService);
disposables.add(extensionEnablementService);
const extensionHostProcessWorker = instantiationService.createInstance(ExtensionHostProcessWorker);
this.threadService = instantiationService.createInstance(MainThreadService, extensionHostProcessWorker.messagingProtocol);

View File

@@ -17,7 +17,7 @@ import { IContextMenuService } from 'vs/platform/contextview/browser/contextView
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
import { ReloadWindowAction } from 'vs/workbench/electron-browser/actions';
import { IExtension, ExtensionState, IExtensionsWorkbenchService, VIEWLET_ID, IExtensionsViewlet, ConfigurationKey } from '../common/extensions';
import { LocalExtensionType } from 'vs/platform/extensionManagement/common/extensionManagement';
import { LocalExtensionType, IExtensionEnablementService } from 'vs/platform/extensionManagement/common/extensionManagement';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { IMessageService } from 'vs/platform/message/common/message';
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
@@ -30,7 +30,7 @@ import { ExtensionsConfigurationInitialContent } from 'vs/workbench/parts/extens
import { IFileService } from 'vs/platform/files/common/files';
import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
import URI from 'vs/base/common/uri';
import { IExtensionService, IExtensionRuntimeService, IExtensionDescription } from 'vs/platform/extensions/common/extensions';
import { IExtensionService, IExtensionDescription } from 'vs/platform/extensions/common/extensions';
import { IWindowService } from 'vs/workbench/services/window/electron-browser/windowService';
const dialog = remote.dialog;
@@ -360,7 +360,7 @@ export class ManageExtensionAction extends Action {
constructor(
@IWorkspaceContextService private workspaceContextService: IWorkspaceContextService,
@IExtensionsWorkbenchService private extensionsWorkbenchService: IExtensionsWorkbenchService,
@IExtensionRuntimeService private extensionRuntimeService: IExtensionRuntimeService,
@IExtensionEnablementService private extensionEnablementService: IExtensionEnablementService,
@IInstantiationService private instantiationService: IInstantiationService
) {
super(ManageExtensionAction.ID);
@@ -409,7 +409,7 @@ export class EnableForWorkspaceAction extends Action implements IExtensionAction
constructor(label: string,
@IWorkspaceContextService private workspaceContextService: IWorkspaceContextService,
@IExtensionsWorkbenchService private extensionsWorkbenchService: IExtensionsWorkbenchService,
@IExtensionRuntimeService private extensionRuntimeService: IExtensionRuntimeService,
@IExtensionEnablementService private extensionEnablementService: IExtensionEnablementService,
@IInstantiationService private instantiationService: IInstantiationService
) {
super(EnableForWorkspaceAction.ID, label);
@@ -421,7 +421,7 @@ export class EnableForWorkspaceAction extends Action implements IExtensionAction
private update(): void {
this.enabled = false;
if (this.extension) {
this.enabled = !this.extension.disabledGlobally && this.extension.disabledForWorkspace && this.extensionRuntimeService.canEnable(this.extension.identifier);
this.enabled = !this.extension.disabledGlobally && this.extension.disabledForWorkspace && this.extensionEnablementService.canEnable(this.extension.identifier);
}
}
@@ -448,7 +448,7 @@ export class EnableGloballyAction extends Action implements IExtensionAction {
constructor(label: string,
@IExtensionsWorkbenchService private extensionsWorkbenchService: IExtensionsWorkbenchService,
@IExtensionRuntimeService private extensionRuntimeService: IExtensionRuntimeService,
@IExtensionEnablementService private extensionEnablementService: IExtensionEnablementService,
@IInstantiationService private instantiationService: IInstantiationService
) {
super(EnableGloballyAction.ID, label);
@@ -460,7 +460,7 @@ export class EnableGloballyAction extends Action implements IExtensionAction {
private update(): void {
this.enabled = false;
if (this.extension) {
this.enabled = this.extension.disabledGlobally && this.extensionRuntimeService.canEnable(this.extension.identifier);
this.enabled = this.extension.disabledGlobally && this.extensionEnablementService.canEnable(this.extension.identifier);
}
}
@@ -493,7 +493,7 @@ export class EnableAction extends Action {
constructor(
@IInstantiationService private instantiationService: IInstantiationService,
@IExtensionsWorkbenchService private extensionsWorkbenchService: IExtensionsWorkbenchService,
@IExtensionRuntimeService private extensionRuntimeService: IExtensionRuntimeService
@IExtensionEnablementService private extensionEnablementService: IExtensionEnablementService
) {
super(EnableAction.ID, localize('enableAction', "Enable"), EnableAction.DisabledClass, false);
@@ -511,7 +511,7 @@ export class EnableAction extends Action {
return;
}
this.enabled = this.extension.state === ExtensionState.Installed && (this.extension.disabledGlobally || this.extension.disabledForWorkspace) && this.extensionRuntimeService.canEnable(this.extension.identifier);
this.enabled = this.extension.state === ExtensionState.Installed && (this.extension.disabledGlobally || this.extension.disabledForWorkspace) && this.extensionEnablementService.canEnable(this.extension.identifier);
this.class = this.enabled ? EnableAction.EnabledClass : EnableAction.DisabledClass;
}
@@ -1204,7 +1204,7 @@ export class DisableAllAction extends Action {
constructor(
id: string = DisableAllAction.ID, label: string = DisableAllAction.LABEL,
@IExtensionsWorkbenchService private extensionsWorkbenchService: IExtensionsWorkbenchService,
@IExtensionRuntimeService private extensionRuntimeService: IExtensionRuntimeService
@IExtensionEnablementService private extensionEnablementService: IExtensionEnablementService
) {
super(id, label);
this.update();
@@ -1236,7 +1236,7 @@ export class DisableAllWorkpsaceAction extends Action {
id: string = DisableAllWorkpsaceAction.ID, label: string = DisableAllWorkpsaceAction.LABEL,
@IWorkspaceContextService private workspaceContextService: IWorkspaceContextService,
@IExtensionsWorkbenchService private extensionsWorkbenchService: IExtensionsWorkbenchService,
@IExtensionRuntimeService private extensionRuntimeService: IExtensionRuntimeService
@IExtensionEnablementService private extensionEnablementService: IExtensionEnablementService
) {
super(id, label);
this.update();
@@ -1267,7 +1267,7 @@ export class EnableAllAction extends Action {
constructor(
id: string = EnableAllAction.ID, label: string = EnableAllAction.LABEL,
@IExtensionsWorkbenchService private extensionsWorkbenchService: IExtensionsWorkbenchService,
@IExtensionRuntimeService private extensionRuntimeService: IExtensionRuntimeService
@IExtensionEnablementService private extensionEnablementService: IExtensionEnablementService
) {
super(id, label);
this.update();
@@ -1275,7 +1275,7 @@ export class EnableAllAction extends Action {
}
private update(): void {
this.enabled = this.extensionsWorkbenchService.local.some(e => this.extensionRuntimeService.canEnable(e.identifier) && e.disabledGlobally);
this.enabled = this.extensionsWorkbenchService.local.some(e => this.extensionEnablementService.canEnable(e.identifier) && e.disabledGlobally);
}
run(): TPromise<any> {
@@ -1299,7 +1299,7 @@ export class EnableAllWorkpsaceAction extends Action {
id: string = EnableAllWorkpsaceAction.ID, label: string = EnableAllWorkpsaceAction.LABEL,
@IWorkspaceContextService private workspaceContextService: IWorkspaceContextService,
@IExtensionsWorkbenchService private extensionsWorkbenchService: IExtensionsWorkbenchService,
@IExtensionRuntimeService private extensionRuntimeService: IExtensionRuntimeService
@IExtensionEnablementService private extensionEnablementService: IExtensionEnablementService
) {
super(id, label);
this.update();
@@ -1307,7 +1307,7 @@ export class EnableAllWorkpsaceAction extends Action {
}
private update(): void {
this.enabled = !!this.workspaceContextService.getWorkspace() && this.extensionsWorkbenchService.local.some(e => this.extensionRuntimeService.canEnable(e.identifier) && !e.disabledGlobally && e.disabledForWorkspace);
this.enabled = !!this.workspaceContextService.getWorkspace() && this.extensionsWorkbenchService.local.some(e => this.extensionEnablementService.canEnable(e.identifier) && !e.disabledGlobally && e.disabledForWorkspace);
}
run(): TPromise<any> {

View File

@@ -22,7 +22,7 @@ import { IPager, mapPager, singlePagePager } from 'vs/base/common/paging';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import {
IExtensionManagementService, IExtensionGalleryService, ILocalExtension, IGalleryExtension, IQueryOptions, IExtensionManifest,
InstallExtensionEvent, DidInstallExtensionEvent, LocalExtensionType, DidUninstallExtensionEvent
InstallExtensionEvent, DidInstallExtensionEvent, LocalExtensionType, DidUninstallExtensionEvent, IExtensionEnablementService
} from 'vs/platform/extensionManagement/common/extensionManagement';
import { getGalleryExtensionTelemetryData, getLocalExtensionTelemetryData } from 'vs/platform/extensionManagement/common/extensionTelemetry';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
@@ -34,7 +34,6 @@ import { IExtension, IExtensionDependencies, ExtensionState, IExtensionsWorkbenc
import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService';
import { IURLService } from 'vs/platform/url/common/url';
import { ExtensionsInput } from 'vs/workbench/parts/extensions/common/extensionsInput';
import { IExtensionRuntimeService } from 'vs/platform/extensions/common/extensions';
import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
interface IExtensionStateProvider {
@@ -299,10 +298,6 @@ export class ExtensionsWorkbenchService implements IExtensionsWorkbenchService {
private autoUpdateDelayer: ThrottledDelayer<void>;
private disposables: IDisposable[] = [];
// TODO: @sandy - Remove these when IExtensionRuntimeService exposes sync API to get extensions.
private newlyInstalled: Extension[] = [];
private unInstalled: Extension[] = [];
private _onChange: Emitter<void> = new Emitter<void>();
get onChange(): Event<void> { return this._onChange.event; }
@@ -315,7 +310,7 @@ export class ExtensionsWorkbenchService implements IExtensionsWorkbenchService {
@ITelemetryService private telemetryService: ITelemetryService,
@IMessageService private messageService: IMessageService,
@IURLService urlService: IURLService,
@IExtensionRuntimeService private extensionRuntimeService: IExtensionRuntimeService,
@IExtensionEnablementService private extensionEnablementService: IExtensionEnablementService,
@IWorkspaceContextService private workspaceContextService: IWorkspaceContextService,
) {
this.stateProvider = ext => this.getExtensionState(ext);
@@ -346,8 +341,8 @@ export class ExtensionsWorkbenchService implements IExtensionsWorkbenchService {
queryLocal(): TPromise<IExtension[]> {
return this.extensionService.getInstalled().then(result => {
const installedById = index(this.installed, e => e.local.id);
const globallyDisabledExtensions = this.extensionRuntimeService.getGloballyDisabledExtensions();
const workspaceDisabledExtensions = this.extensionRuntimeService.getWorkspaceDisabledExtensions();
const globallyDisabledExtensions = this.extensionEnablementService.getGloballyDisabledExtensions();
const workspaceDisabledExtensions = this.extensionEnablementService.getWorkspaceDisabledExtensions();
this.installed = result.map(local => {
const extension = installedById[local.id] || new Extension(this.galleryService, this.stateProvider, local);
extension.local = local;
@@ -489,12 +484,7 @@ export class ExtensionsWorkbenchService implements IExtensionsWorkbenchService {
}
return this.doSetEnablement(extension, enable, workspace).then(reload => {
// update the disable flags
const globallyDisabledExtensions = this.extensionRuntimeService.getGloballyDisabledExtensions();
const workspaceDisabledExtensions = this.extensionRuntimeService.getWorkspaceDisabledExtensions();
extension.disabledGlobally = globallyDisabledExtensions.indexOf(extension.identifier) !== -1;
extension.disabledForWorkspace = workspaceDisabledExtensions.indexOf(extension.identifier) !== -1;
this.updatedDisableFlags(extension);
this.telemetryService.publicLog(enable ? 'extension:enable' : 'extension:disable', extension.telemetryData);
this._onChange.fire();
});
@@ -517,14 +507,14 @@ export class ExtensionsWorkbenchService implements IExtensionsWorkbenchService {
private doSetEnablement(extension: IExtension, enable: boolean, workspace: boolean): TPromise<boolean> {
if (workspace) {
return this.extensionRuntimeService.setEnablement(extension.identifier, enable, workspace);
return this.extensionEnablementService.setEnablement(extension.identifier, enable, workspace);
}
const globalElablement = this.extensionRuntimeService.setEnablement(extension.identifier, enable, false);
const globalElablement = this.extensionEnablementService.setEnablement(extension.identifier, enable, false);
if (!this.workspaceContextService.getWorkspace()) {
return globalElablement;
}
return TPromise.join([globalElablement, this.extensionRuntimeService.setEnablement(extension.identifier, enable, true)])
return TPromise.join([globalElablement, this.extensionEnablementService.setEnablement(extension.identifier, enable, true)])
.then(values => values[0] || values[1]);
}
@@ -560,7 +550,6 @@ export class ExtensionsWorkbenchService implements IExtensionsWorkbenchService {
this.installing = this.installing.filter(e => e.id !== id);
if (!error) {
this.newlyInstalled.push(extension);
extension.local = local;
const galleryId = local.metadata && local.metadata.id;
@@ -599,10 +588,7 @@ export class ExtensionsWorkbenchService implements IExtensionsWorkbenchService {
}
private onDidUninstallExtension({id, error}: DidUninstallExtensionEvent): void {
let newlyInstalled = false;
if (!error) {
newlyInstalled = this.newlyInstalled.filter(e => e.local.id === id).length > 0;
this.newlyInstalled = this.newlyInstalled.filter(e => e.local.id !== id);
this.installed = this.installed.filter(e => e.local.id !== id);
}
@@ -613,17 +599,20 @@ export class ExtensionsWorkbenchService implements IExtensionsWorkbenchService {
}
if (!error) {
this.unInstalled.push(uninstalling.extension);
const globallyDisabledExtensions = this.extensionRuntimeService.getGloballyDisabledExtensions();
const workspaceDisabledExtensions = this.extensionRuntimeService.getWorkspaceDisabledExtensions();
uninstalling.extension.disabledGlobally = globallyDisabledExtensions.indexOf(uninstalling.extension.identifier) !== -1;
uninstalling.extension.disabledForWorkspace = workspaceDisabledExtensions.indexOf(uninstalling.extension.identifier) !== -1;
this.updatedDisableFlags(uninstalling.extension);
this.reportTelemetry(uninstalling, true);
}
this._onChange.fire();
}
private updatedDisableFlags(extension: IExtension) {
const globallyDisabledExtensions = this.extensionEnablementService.getGloballyDisabledExtensions();
const workspaceDisabledExtensions = this.extensionEnablementService.getWorkspaceDisabledExtensions();
extension.disabledGlobally = globallyDisabledExtensions.indexOf(extension.identifier) !== -1;
extension.disabledForWorkspace = workspaceDisabledExtensions.indexOf(extension.identifier) !== -1;
}
private getExtensionState(extension: Extension): ExtensionState {
if (extension.gallery && this.installing.some(e => e.extension.gallery.id === extension.gallery.id)) {
return ExtensionState.Installing;

View File

@@ -1,144 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { localize } from 'vs/nls';
import { TPromise } from 'vs/base/common/winjs.base';
import { distinct } from 'vs/base/common/arrays';
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
import { IExtensionManagementService, DidUninstallExtensionEvent } from 'vs/platform/extensionManagement/common/extensionManagement';
import { IWorkspaceContextService, IWorkspace } from 'vs/platform/workspace/common/workspace';
import { IExtensionRuntimeService } from 'vs/platform/extensions/common/extensions';
import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage';
import { IMessageService } from 'vs/platform/message/common/message';
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
const DISABLED_EXTENSIONS_STORAGE_PATH = 'extensions/disabled';
export class ExtensionRuntimeService implements IExtensionRuntimeService {
_serviceBrand: any;
private workspace: IWorkspace;
private disposables: IDisposable[] = [];
constructor(
@IStorageService private storageService: IStorageService,
@IWorkspaceContextService contextService: IWorkspaceContextService,
@IMessageService private messageService: IMessageService,
@IEnvironmentService private environmentService: IEnvironmentService,
@IExtensionManagementService private extensionManagementService: IExtensionManagementService
) {
this.workspace = contextService.getWorkspace();
extensionManagementService.onDidUninstallExtension(this.onDidUninstallExtension, this, this.disposables);
}
public getGloballyDisabledExtensions(): string[] {
return this.getDisabledExtensionsFromStorage(StorageScope.GLOBAL);
}
public getWorkspaceDisabledExtensions(): string[] {
return this.getDisabledExtensionsFromStorage(StorageScope.WORKSPACE);
}
public canEnable(identifier: string): boolean {
return !this.environmentService.disableExtensions && this.isDisabled(identifier);
}
public setEnablement(identifier: string, enable: boolean, workspace: boolean = false): TPromise<boolean> {
if (workspace && !this.workspace) {
return TPromise.wrapError(localize('noWorkspace', "No workspace."));
}
if (this.environmentService.disableExtensions) {
return TPromise.wrap(false);
}
if (this.isDisabled(identifier) === !enable) {
return TPromise.wrap(false);
}
if (enable) {
if (workspace) {
this.enableExtension(identifier, StorageScope.WORKSPACE);
} else {
this.enableExtension(identifier, StorageScope.GLOBAL);
}
} else {
if (workspace) {
this.disableExtension(identifier, StorageScope.WORKSPACE);
} else {
this.disableExtension(identifier, StorageScope.GLOBAL);
}
}
return TPromise.wrap(true);
}
private getDisabledExtensions(): string[] {
const globalDisabledExtensions = this.getGloballyDisabledExtensions();
const workspaceDisabledExtensions = this.getWorkspaceDisabledExtensions();
return distinct([...workspaceDisabledExtensions, ...globalDisabledExtensions]);
}
private isDisabled(identifier: string): boolean {
return this.getDisabledExtensions().indexOf(identifier) !== -1;
}
private getDisabledExtensionsFromStorage(scope?: StorageScope): string[] {
if (scope !== void 0) {
return this._getDisabledExtensions(scope);
}
const globallyDisabled = this._getDisabledExtensions(StorageScope.GLOBAL);
const workspaceDisabled = this._getDisabledExtensions(StorageScope.WORKSPACE);
return [...globallyDisabled, ...workspaceDisabled];
}
private disableExtension(identifier: string, scope: StorageScope): TPromise<boolean> {
let disabledExtensions = this._getDisabledExtensions(scope);
disabledExtensions.push(identifier);
this._setDisabledExtensions(disabledExtensions, scope);
return TPromise.wrap(true);
}
private enableExtension(identifier: string, scope: StorageScope): TPromise<boolean> {
let disabledExtensions = this._getDisabledExtensions(scope);
const index = disabledExtensions.indexOf(identifier);
if (index !== -1) {
disabledExtensions.splice(index, 1);
this._setDisabledExtensions(disabledExtensions, scope);
}
return TPromise.wrap(true);
}
private _getDisabledExtensions(scope: StorageScope): string[] {
const value = this.storageService.get(DISABLED_EXTENSIONS_STORAGE_PATH, scope, '');
return value ? distinct(value.split(',')) : [];
}
private _setDisabledExtensions(disabledExtensions: string[], scope: StorageScope): void {
if (disabledExtensions.length) {
this.storageService.store(DISABLED_EXTENSIONS_STORAGE_PATH, disabledExtensions.join(','), scope);
} else {
this.storageService.remove(DISABLED_EXTENSIONS_STORAGE_PATH, scope);
}
}
private onDidUninstallExtension({id, error}: DidUninstallExtensionEvent): void {
if (!error) {
id = stripVersion(id);
this.enableExtension(id, StorageScope.WORKSPACE);
this.enableExtension(id, StorageScope.GLOBAL);
}
}
dispose(): void {
this.disposables = dispose(this.disposables);
}
}
function stripVersion(id: string): string {
return id.replace(/-\d+\.\d+\.\d+$/, '');
}