Skip to content

Commit 6221b0c

Browse files
author
Kartik Raj
committed
Only activate interpreter and language server component when in a virtual workspace
1 parent cebb407 commit 6221b0c

File tree

11 files changed

+58
-82
lines changed

11 files changed

+58
-82
lines changed

src/client/activation/activationManager.ts

+21-20
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,10 @@ import { IInterpreterAutoSelectionService } from '../interpreter/autoSelection/t
1616
import { traceDecoratorError } from '../logging';
1717
import { sendActivationTelemetry } from '../telemetry/envFileTelemetry';
1818
import {
19+
ComponentId,
1920
IExtensionActivationManager,
2021
IExtensionActivationService,
2122
IExtensionSingleActivationService,
22-
ILanguageServerActivation,
2323
} from './types';
2424

2525
@injectable()
@@ -44,7 +44,6 @@ export class ExtensionActivationManager implements IExtensionActivationManager {
4444
@inject(IActiveResourceService) private readonly activeResourceService: IActiveResourceService,
4545
@inject(IExperimentService) private readonly experiments: IExperimentService,
4646
@inject(IInterpreterPathService) private readonly interpreterPathService: IInterpreterPathService,
47-
@inject(ILanguageServerActivation) private readonly languageServerActivation: ILanguageServerActivation,
4847
) {}
4948

5049
public dispose(): void {
@@ -63,14 +62,14 @@ export class ExtensionActivationManager implements IExtensionActivationManager {
6362

6463
// Activate all activation services together.
6564

66-
if (this.workspaceService.isVirtualWorkspace) {
67-
await this.activateWorkspace(this.activeResourceService.getActiveResource());
68-
} else {
69-
await Promise.all([
70-
...this.singleActivationServices.map((item) => item.activate()),
71-
this.activateWorkspace(this.activeResourceService.getActiveResource()),
72-
]);
73-
}
65+
const singleActivationServices = this.workspaceService.isVirtualWorkspace
66+
? this.singleActivationServices.filter((s) => s.componentId === ComponentId.interpreter)
67+
: this.singleActivationServices;
68+
69+
await Promise.all([
70+
...singleActivationServices.map((item) => item.activate()),
71+
this.activateWorkspace(this.activeResourceService.getActiveResource()),
72+
]);
7473
}
7574

7675
@traceDecoratorError('Failed to activate a workspace')
@@ -81,18 +80,20 @@ export class ExtensionActivationManager implements IExtensionActivationManager {
8180
}
8281
this.activatedWorkspaces.add(key);
8382

83+
if (this.experiments.inExperimentSync(DeprecatePythonPath.experiment)) {
84+
await this.interpreterPathService.copyOldInterpreterStorageValuesToNew(resource);
85+
}
86+
8487
await sendActivationTelemetry(this.fileSystem, this.workspaceService, resource);
8588

86-
if (this.workspaceService.isVirtualWorkspace) {
87-
await this.languageServerActivation.activate(resource);
88-
} else {
89-
if (this.experiments.inExperimentSync(DeprecatePythonPath.experiment)) {
90-
await this.interpreterPathService.copyOldInterpreterStorageValuesToNew(resource);
91-
}
92-
await this.autoSelection.autoSelectInterpreter(resource);
93-
await Promise.all(this.activationServices.map((item) => item.activate(resource)));
94-
await this.appDiagnostics.performPreStartupHealthCheck(resource);
95-
}
89+
await this.autoSelection.autoSelectInterpreter(resource);
90+
const activationServices = this.workspaceService.isVirtualWorkspace
91+
? this.activationServices.filter(
92+
(s) => s.componentId === ComponentId.interpreter || s.componentId === ComponentId.languageServer,
93+
)
94+
: this.activationServices;
95+
await Promise.all(activationServices.map((item) => item.activate(resource)));
96+
await this.appDiagnostics.performPreStartupHealthCheck(resource);
9697
}
9798

9899
public async initialize(): Promise<void> {

src/client/activation/activationService.ts

+8-9
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import { EventName } from '../telemetry/constants';
2525
import { LanguageServerChangeHandler } from './common/languageServerChangeHandler';
2626
import { RefCountedLanguageServer } from './refCountedLanguageServer';
2727
import {
28+
ComponentId,
2829
IExtensionActivationService,
2930
ILanguageServerActivator,
3031
ILanguageServerCache,
@@ -49,13 +50,15 @@ export class LanguageServerExtensionActivationService
4950

5051
private activatedServer?: IActivatedServer;
5152

53+
public readonly componentId? = ComponentId.languageServer;
54+
5255
private readonly workspaceService: IWorkspaceService;
5356

5457
private readonly configurationService: IConfigurationService;
5558

5659
private readonly output: OutputChannel;
5760

58-
private readonly interpreterService?: IInterpreterService;
61+
private readonly interpreterService: IInterpreterService;
5962

6063
private readonly languageServerChangeHandler: LanguageServerChangeHandler;
6164

@@ -67,18 +70,14 @@ export class LanguageServerExtensionActivationService
6770
) {
6871
this.workspaceService = this.serviceContainer.get<IWorkspaceService>(IWorkspaceService);
6972
this.configurationService = this.serviceContainer.get<IConfigurationService>(IConfigurationService);
70-
if (!this.workspaceService.isVirtualWorkspace) {
71-
this.interpreterService = this.serviceContainer.get<IInterpreterService>(IInterpreterService);
72-
}
73+
this.interpreterService = this.serviceContainer.get<IInterpreterService>(IInterpreterService);
7374
this.output = this.serviceContainer.get<OutputChannel>(IOutputChannel, STANDARD_OUTPUT_CHANNEL);
7475

7576
const disposables = serviceContainer.get<IDisposableRegistry>(IDisposableRegistry);
7677
disposables.push(this);
7778
disposables.push(this.workspaceService.onDidChangeConfiguration(this.onDidChangeConfiguration.bind(this)));
7879
disposables.push(this.workspaceService.onDidChangeWorkspaceFolders(this.onWorkspaceFoldersChanged, this));
79-
if (this.interpreterService) {
80-
disposables.push(this.interpreterService.onDidChangeInterpreter(this.onDidChangeInterpreter.bind(this)));
81-
}
80+
disposables.push(this.interpreterService.onDidChangeInterpreter(this.onDidChangeInterpreter.bind(this)));
8281

8382
this.languageServerChangeHandler = new LanguageServerChangeHandler(
8483
this.getCurrentLanguageServerType(),
@@ -95,7 +94,7 @@ export class LanguageServerExtensionActivationService
9594
const stopWatch = new StopWatch();
9695
// Get a new server and dispose of the old one (might be the same one)
9796
this.resource = resource;
98-
const interpreter = await this.interpreterService?.getActiveInterpreter(resource);
97+
const interpreter = await this.interpreterService.getActiveInterpreter(resource);
9998
const key = await this.getKey(resource, interpreter);
10099

101100
// If we have an old server with a different key, then deactivate it as the
@@ -307,7 +306,7 @@ export class LanguageServerExtensionActivationService
307306
resource,
308307
workspacePathNameForGlobalWorkspaces,
309308
);
310-
interpreter = interpreter || (await this.interpreterService?.getActiveInterpreter(resource));
309+
interpreter = interpreter || (await this.interpreterService.getActiveInterpreter(resource));
311310
const interperterPortion = interpreter ? `${interpreter.path}-${interpreter.envName}` : '';
312311
return `${resourcePortion}-${interperterPortion}`;
313312
}

src/client/activation/serviceRegistry.ts

-2
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ import {
2222
IExtensionActivationService,
2323
IExtensionSingleActivationService,
2424
ILanguageClientFactory,
25-
ILanguageServerActivation,
2625
ILanguageServerActivator,
2726
ILanguageServerAnalysisOptions,
2827
ILanguageServerCache,
@@ -38,7 +37,6 @@ import { LoadLanguageServerExtension } from './common/loadLanguageServerExtensio
3837
export function registerTypes(serviceManager: IServiceManager, languageServerType: LanguageServerType): void {
3938
serviceManager.addSingleton<ILanguageServerCache>(ILanguageServerCache, LanguageServerExtensionActivationService);
4039
serviceManager.addBinding(ILanguageServerCache, IExtensionActivationService);
41-
serviceManager.addBinding(ILanguageServerCache, ILanguageServerActivation);
4240
serviceManager.add<IExtensionActivationManager>(IExtensionActivationManager, ExtensionActivationManager);
4341
serviceManager.add<ILanguageServerActivator>(
4442
ILanguageServerActivator,

src/client/activation/types.ts

+8-3
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ export const IExtensionActivationService = Symbol('IExtensionActivationService')
5858
* @interface IExtensionActivationService
5959
*/
6060
export interface IExtensionActivationService {
61+
componentId?: ComponentId;
6162
activate(resource: Resource): Promise<void>;
6263
}
6364

@@ -104,9 +105,6 @@ export interface ILanguageServerCache {
104105
get(resource: Resource, interpreter?: PythonEnvironment): Promise<ILanguageServer>;
105106
}
106107

107-
export const ILanguageServerActivation = Symbol('ILanguageServerActivation');
108-
export interface ILanguageServerActivation extends IExtensionActivationService {}
109-
110108
export type FolderVersionPair = { path: string; version: SemVer };
111109
export const ILanguageServerFolderService = Symbol('ILanguageServerFolderService');
112110

@@ -171,6 +169,12 @@ export interface ILanguageServerOutputChannel {
171169
readonly channel: IOutputChannel;
172170
}
173171

172+
export enum ComponentId {
173+
other = 0,
174+
interpreter = 1,
175+
languageServer = 2,
176+
}
177+
174178
export const IExtensionSingleActivationService = Symbol('IExtensionSingleActivationService');
175179
/**
176180
* Classes implementing this interface will have their `activate` methods
@@ -181,5 +185,6 @@ export const IExtensionSingleActivationService = Symbol('IExtensionSingleActivat
181185
* @interface IExtensionSingleActivationService
182186
*/
183187
export interface IExtensionSingleActivationService {
188+
componentId?: ComponentId;
184189
activate(): Promise<void>;
185190
}

src/client/extension.ts

+9-18
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,6 @@ import { sendErrorTelemetry, sendStartupTelemetry } from './startupTelemetry';
4242
import { IStartupDurations } from './types';
4343
import { runAfterActivation } from './common/utils/runAfterActivation';
4444
import { IInterpreterService } from './interpreter/contracts';
45-
import { WorkspaceService } from './common/application/workspace';
4645

4746
durations.codeLoadingTime = stopWatch.elapsedTime;
4847

@@ -70,12 +69,9 @@ export async function activate(context: IExtensionContext): Promise<IExtensionAp
7069
// Send the "success" telemetry only if activation did not fail.
7170
// Otherwise Telemetry is send via the error handler.
7271

73-
const workspace = new WorkspaceService();
74-
if (!workspace.isVirtualWorkspace) {
75-
sendStartupTelemetry(ready, durations, stopWatch, serviceContainer)
76-
// Run in the background.
77-
.ignoreErrors();
78-
}
72+
sendStartupTelemetry(ready, durations, stopWatch, serviceContainer)
73+
// Run in the background.
74+
.ignoreErrors();
7975
return api;
8076
}
8177

@@ -137,13 +133,11 @@ async function activateUnsafe(
137133
setTimeout(async () => {
138134
if (activatedServiceContainer) {
139135
const workspaceService = activatedServiceContainer.get<IWorkspaceService>(IWorkspaceService);
140-
if (!workspaceService.isVirtualWorkspace) {
141-
const interpreterManager = activatedServiceContainer.get<IInterpreterService>(IInterpreterService);
142-
const workspaces = workspaceService.workspaceFolders ?? [];
143-
await interpreterManager
144-
.refresh(workspaces.length > 0 ? workspaces[0].uri : undefined)
145-
.catch((ex) => traceError('Python Extension: interpreterManager.refresh', ex));
146-
}
136+
const interpreterManager = activatedServiceContainer.get<IInterpreterService>(IInterpreterService);
137+
const workspaces = workspaceService.workspaceFolders ?? [];
138+
await interpreterManager
139+
.refresh(workspaces.length > 0 ? workspaces[0].uri : undefined)
140+
.catch((ex) => traceError('Python Extension: interpreterManager.refresh', ex));
147141
}
148142

149143
runAfterActivation();
@@ -167,10 +161,7 @@ async function handleError(ex: Error, startupDurations: IStartupDurations) {
167161
);
168162
traceError('extension activation failed', ex);
169163

170-
const workspace = new WorkspaceService();
171-
if (!workspace.isVirtualWorkspace) {
172-
await sendErrorTelemetry(ex, startupDurations, activatedServiceContainer);
173-
}
164+
await sendErrorTelemetry(ex, startupDurations, activatedServiceContainer);
174165
}
175166

176167
interface IAppShell {

src/client/extensionActivation.ts

+4-11
Original file line numberDiff line numberDiff line change
@@ -70,11 +70,6 @@ export async function activateComponents(
7070
// https://github.com/microsoft/vscode-python/issues/15380
7171
// These will go away eventually once everything is refactored into components.
7272
const legacyActivationResult = await activateLegacy(ext);
73-
const workspaceService = ext.legacyIOC.serviceContainer.get<IWorkspaceService>(IWorkspaceService);
74-
if (workspaceService.isVirtualWorkspace) {
75-
// Nothing other than Pylance is activated when using virtual workspaces.
76-
return [legacyActivationResult];
77-
}
7873
const promises: Promise<ActivationResult>[] = [
7974
// More component activations will go here
8075
pythonEnvironments.activate(components.pythonEnvs, ext),
@@ -122,8 +117,9 @@ async function activateLegacy(ext: ExtensionState): Promise<ActivationResult> {
122117
// directly queries VSCode API.
123118
setLoggingLevel(getLoggingLevel());
124119

125-
// `IConfigurationService` may depend any of the registered types, so doing it after all registrations are finished.
126120
const configuration = serviceManager.get<IConfigurationService>(IConfigurationService);
121+
// Settings are dependent on Experiment service, so we need to initialize it after experiments are activated.
122+
serviceContainer.get<IConfigurationService>(IConfigurationService).getSettings().initialize();
127123
const languageServerType = configuration.getSettings().languageServer;
128124

129125
// Language feature registrations.
@@ -137,12 +133,12 @@ async function activateLegacy(ext: ExtensionState): Promise<ActivationResult> {
137133
const workspaceService = serviceContainer.get<IWorkspaceService>(IWorkspaceService);
138134
const cmdManager = serviceContainer.get<ICommandManager>(ICommandManager);
139135
languages.setLanguageConfiguration(PYTHON_LANGUAGE, getLanguageConfiguration());
136+
const interpreterManager = serviceContainer.get<IInterpreterService>(IInterpreterService);
137+
interpreterManager.initialize();
140138
if (!workspaceService.isVirtualWorkspace) {
141139
const handlers = serviceManager.getAll<IDebugSessionEventHandlers>(IDebugSessionEventHandlers);
142140
const dispatcher = new DebugSessionEventDispatcher(handlers, DebugService.instance, disposables);
143141
dispatcher.registerEventHandlers();
144-
const interpreterManager = serviceContainer.get<IInterpreterService>(IInterpreterService);
145-
interpreterManager.initialize();
146142

147143
const outputChannel = serviceManager.get<OutputChannel>(IOutputChannel, STANDARD_OUTPUT_CHANNEL);
148144
disposables.push(cmdManager.registerCommand(Commands.ViewOutput, () => outputChannel.show()));
@@ -194,9 +190,6 @@ async function activateLegacy(ext: ExtensionState): Promise<ActivationResult> {
194190
const manager = serviceContainer.get<IExtensionActivationManager>(IExtensionActivationManager);
195191
context.subscriptions.push(manager);
196192

197-
// Settings are dependent on Experiment service, so we need to initialize it after experiments are activated.
198-
serviceContainer.get<IConfigurationService>(IConfigurationService).getSettings().initialize();
199-
200193
const activationPromise = manager.activate();
201194

202195
return { fullyReady: activationPromise };

src/client/interpreter/configuration/interpreterSelector/commands/base.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,15 @@
66
import { injectable, unmanaged } from 'inversify';
77
import * as path from 'path';
88
import { ConfigurationTarget, Disposable, QuickPickItem, Uri } from 'vscode';
9-
import { IExtensionSingleActivationService } from '../../../../activation/types';
9+
import { ComponentId, IExtensionSingleActivationService } from '../../../../activation/types';
1010
import { IApplicationShell, ICommandManager, IWorkspaceService } from '../../../../common/application/types';
1111
import { IDisposable, Resource } from '../../../../common/types';
1212
import { Interpreters } from '../../../../common/utils/localize';
1313
import { IPythonPathUpdaterServiceManager } from '../../types';
1414

1515
@injectable()
1616
export abstract class BaseInterpreterSelectorCommand implements IExtensionSingleActivationService, IDisposable {
17+
public readonly componentId = ComponentId.interpreter;
1718
protected disposables: Disposable[] = [];
1819
constructor(
1920
@unmanaged() protected readonly pythonPathUpdaterService: IPythonPathUpdaterServiceManager,

src/client/interpreter/virtualEnvs/condaInheritEnvPrompt.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
import { inject, injectable, optional } from 'inversify';
55
import { ConfigurationTarget, Uri } from 'vscode';
6-
import { IExtensionActivationService } from '../../activation/types';
6+
import { ComponentId, IExtensionActivationService } from '../../activation/types';
77
import { IApplicationShell, IWorkspaceService } from '../../common/application/types';
88
import { IPlatformService } from '../../common/platform/types';
99
import { IBrowserService, IPersistentStateFactory } from '../../common/types';
@@ -18,6 +18,7 @@ export const condaInheritEnvPromptKey = 'CONDA_INHERIT_ENV_PROMPT_KEY';
1818

1919
@injectable()
2020
export class CondaInheritEnvPrompt implements IExtensionActivationService {
21+
public readonly componentId = ComponentId.interpreter;
2122
constructor(
2223
@inject(IInterpreterService) private readonly interpreterService: IInterpreterService,
2324
@inject(IWorkspaceService) private readonly workspaceService: IWorkspaceService,

src/client/interpreter/virtualEnvs/virtualEnvPrompt.ts

+3-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
import { inject, injectable } from 'inversify';
55
import { ConfigurationTarget, Disposable, Uri } from 'vscode';
6-
import { IExtensionActivationService } from '../../activation/types';
6+
import { ComponentId, IExtensionActivationService } from '../../activation/types';
77
import { IApplicationShell } from '../../common/application/types';
88
import { IDisposableRegistry, IPersistentStateFactory } from '../../common/types';
99
import { sleep } from '../../common/utils/async';
@@ -18,6 +18,8 @@ import { IComponentAdapter, IInterpreterHelper } from '../contracts';
1818
const doNotDisplayPromptStateKey = 'MESSAGE_KEY_FOR_VIRTUAL_ENV';
1919
@injectable()
2020
export class VirtualEnvironmentPrompt implements IExtensionActivationService {
21+
public readonly componentId = ComponentId.interpreter;
22+
2123
constructor(
2224
@inject(IPersistentStateFactory) private readonly persistentStateFactory: IPersistentStateFactory,
2325
@inject(IInterpreterHelper) private readonly helper: IInterpreterHelper,

src/client/jupyter/jupyterIntegration.ts

-5
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ import { dirname } from 'path';
99
import { CancellationToken, Disposable, Event, Extension, Memento, Uri } from 'vscode';
1010
import * as lsp from 'vscode-languageserver-protocol';
1111
import { ILanguageServerCache, ILanguageServerConnection } from '../activation/types';
12-
import { IWorkspaceService } from '../common/application/types';
1312
import { JUPYTER_EXTENSION_ID } from '../common/constants';
1413
import { InterpreterUri, ModuleInstallFlags } from '../common/installer/types';
1514
import {
@@ -177,14 +176,10 @@ export class JupyterExtensionIntegration {
177176
@inject(IMemento) @named(GLOBAL_MEMENTO) private globalState: Memento,
178177
@inject(IInterpreterDisplay) private interpreterDisplay: IInterpreterDisplay,
179178
@inject(IComponentAdapter) private pyenvs: IComponentAdapter,
180-
@inject(IWorkspaceService) private workspace: IWorkspaceService,
181179
) {}
182180

183181
public registerApi(jupyterExtensionApi: JupyterExtensionApi): JupyterExtensionApi | undefined {
184182
// Forward python parts
185-
if (this.workspace.isVirtualWorkspace) {
186-
return undefined;
187-
}
188183
jupyterExtensionApi.registerPythonApi({
189184
onDidChangeInterpreter: this.interpreterService.onDidChangeInterpreter,
190185
getActiveInterpreter: async (resource?: Uri) => this.interpreterService.getActiveInterpreter(resource),

0 commit comments

Comments
 (0)