Repository: microsoft/vscode (TypeScript)
Date: 2022-06-27 10:37:36+00:00
Task type: Bug Fix

Issue:
Profiles: switching between profiles resets extension state
1. Create a new profile (empty)
2. Switch back to the default
3. :bug: extensions and states are reset

This is really annoying as I have +100 extensions and now have to go in and reset most of what I had. I would say that this is also a blocking bug where I won't be using the feature again until this is fixed.

## Before
![image](https://user-images.githubusercontent.com/35271042/175553205-5e75ac4b-762f-4781-a5d6-85c4ac191eb5.png)

## After
<img width="1232" alt="CleanShot 2022-06-24 at 07 10 30@2x" src="https://user-images.githubusercontent.com/35271042/175553385-2aab413e-4b05-4b1b-a9b9-1e64f5d19ff4.png">



Issue discussion:
Ok so reloading the windows actually restored everything back, maybe this is a limitation in the switching of profiles of the initial state? I was just about to disable my extensions again but decided to reload just in case and saw it fixed. Can see a lot of people being confused/frustrated and would rather see a forced reload than a nice transition with a state that is stuck.
Thanks for the feedback.

Sorry about it. This is a bug while transitioning from one profile to another profile. State is restored but model is not updated.

Solution patch:
diff --git a/src/vs/workbench/services/extensionManagement/browser/extensionEnablementService.ts b/src/vs/workbench/services/extensionManagement/browser/extensionEnablementService.ts
--- a/src/vs/workbench/services/extensionManagement/browser/extensionEnablementService.ts
+++ b/src/vs/workbench/services/extensionManagement/browser/extensionEnablementService.ts
@@ -580,9 +580,9 @@ export class ExtensionEnablementService extends Disposable implements IWorkbench
 	}
 
 	private _onDidChangeExtensions(added: ReadonlyArray<IExtension>, removed: ReadonlyArray<IExtension>): void {
-		const disabledByTrustExtensions = added.filter(e => this.getEnablementState(e) === EnablementState.DisabledByTrustRequirement);
-		if (disabledByTrustExtensions.length) {
-			this._onEnablementChanged.fire(disabledByTrustExtensions);
+		const disabledExtensions = added.filter(e => !this.isEnabledEnablementState(this.getEnablementState(e)));
+		if (disabledExtensions.length) {
+			this._onEnablementChanged.fire(disabledExtensions);
 		}
 		removed.forEach(({ identifier }) => this._reset(identifier));
 	}


Test patch:
diff --git a/src/vs/workbench/services/extensionManagement/test/browser/extensionEnablementService.test.ts b/src/vs/workbench/services/extensionManagement/test/browser/extensionEnablementService.test.ts
--- a/src/vs/workbench/services/extensionManagement/test/browser/extensionEnablementService.test.ts
+++ b/src/vs/workbench/services/extensionManagement/test/browser/extensionEnablementService.test.ts
@@ -5,10 +5,10 @@
 import * as assert from 'assert';
 import * as sinon from 'sinon';
 import { IExtensionManagementService, DidUninstallExtensionEvent, ILocalExtension, InstallExtensionEvent, InstallExtensionResult, UninstallExtensionEvent } from 'vs/platform/extensionManagement/common/extensionManagement';
-import { IWorkbenchExtensionEnablementService, EnablementState, IExtensionManagementServerService, IExtensionManagementServer, IWorkbenchExtensionManagementService, ExtensionInstallLocation, IProfileAwareExtensionManagementService } from 'vs/workbench/services/extensionManagement/common/extensionManagement';
+import { IWorkbenchExtensionEnablementService, EnablementState, IExtensionManagementServerService, IExtensionManagementServer, IWorkbenchExtensionManagementService, ExtensionInstallLocation, IProfileAwareExtensionManagementService, DidChangeProfileExtensionsEvent } from 'vs/workbench/services/extensionManagement/common/extensionManagement';
 import { ExtensionEnablementService } from 'vs/workbench/services/extensionManagement/browser/extensionEnablementService';
 import { TestInstantiationService } from 'vs/platform/instantiation/test/common/instantiationServiceMock';
-import { Emitter, Event } from 'vs/base/common/event';
+import { Emitter } from 'vs/base/common/event';
 import { IWorkspace, IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace';
 import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';
 import { IStorageService, InMemoryStorageService } from 'vs/platform/storage/common/storage';
@@ -116,6 +116,7 @@ suite('ExtensionEnablementService Test', () => {
 
 	const didInstallEvent = new Emitter<readonly InstallExtensionResult[]>();
 	const didUninstallEvent = new Emitter<DidUninstallExtensionEvent>();
+	const didChangeProfileExtensionsEvent = new Emitter<DidChangeProfileExtensionsEvent>();
 	const installed: ILocalExtension[] = [];
 
 	setup(() => {
@@ -128,7 +129,7 @@ suite('ExtensionEnablementService Test', () => {
 			extensionManagementService: <IProfileAwareExtensionManagementService>{
 				onDidInstallExtensions: didInstallEvent.event,
 				onDidUninstallExtension: didUninstallEvent.event,
-				onDidChangeProfileExtensions: Event.None,
+				onDidChangeProfileExtensions: didChangeProfileExtensionsEvent.event,
 				getInstalled: () => Promise.resolve(installed)
 			},
 		}, null, null));
@@ -950,6 +951,22 @@ suite('ExtensionEnablementService Test', () => {
 		assert.deepStrictEqual((<IExtension>target.args[0][0][1]).identifier, { id: 'pub.c' });
 	});
 
+	test('test adding an extension that was disabled', async () => {
+		const extension = aLocalExtension('pub.a');
+		installed.push(extension);
+		testObject = new TestExtensionEnablementService(instantiationService);
+		await testObject.setEnablement([extension], EnablementState.DisabledGlobally);
+
+		const target = sinon.spy();
+		testObject.onEnablementChanged(target);
+		didChangeProfileExtensionsEvent.fire({ added: [extension], removed: [] });
+
+		assert.ok(!testObject.isEnabled(extension));
+		assert.strictEqual(testObject.getEnablementState(extension), EnablementState.DisabledGlobally);
+		assert.strictEqual(target.args[0][0].length, 1);
+		assert.deepStrictEqual((<IExtension>target.args[0][0][0]).identifier, { id: 'pub.a' });
+	});
+
 });
 
 function anExtensionManagementServer(authority: string, instantiationService: TestInstantiationService): IExtensionManagementServer {