Skip to content

Commit d4644dc

Browse files
author
Kartik Raj
authored
Only activate language servers when running in virtual workspaces (#17519)
* Only activate Pylance when running in virtual workspaces * News entry * Trigger intelliSense analysis for all schemes of python code * Also support Jedi in virtual workspaces * Rebase with main * Oops * Only support known virtual workspace scheme * Look into all python schemes when in a virtual workspace * Fix some tests * Fix mistake * Do not register Jupyter hooks when using virtual workspaces * Nit * Only activate interpreter and language server component when in a virtual workspace * Make component id a mandatory field in extension activation services * Refactor * Use supported workspace types instead of component id * Fix lint * Code reviwes
1 parent 64118ff commit d4644dc

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+169
-73
lines changed

news/1 Enhancements/17519.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Declare limited support when running in virtual workspaces by only supporting language servers.

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@
1111
"supported": false
1212
},
1313
"virtualWorkspaces": {
14-
"supported": false,
15-
"description": "Limited support on the web."
14+
"supported": "limited",
15+
"description": "Only Partial IntelliSense supported."
1616
}
1717
},
1818
"languageServerVersion": "0.5.30",

src/client/activation/activationManager.ts

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,16 @@ export class ExtensionActivationManager implements IExtensionActivationManager {
3939
@inject(IActiveResourceService) private readonly activeResourceService: IActiveResourceService,
4040
@inject(IExperimentService) private readonly experiments: IExperimentService,
4141
@inject(IInterpreterPathService) private readonly interpreterPathService: IInterpreterPathService,
42-
) {}
42+
) {
43+
if (this.workspaceService.isVirtualWorkspace) {
44+
this.activationServices = this.activationServices.filter(
45+
(service) => service.supportedWorkspaceTypes.virtualWorkspace,
46+
);
47+
this.singleActivationServices = this.singleActivationServices.filter(
48+
(service) => service.supportedWorkspaceTypes.virtualWorkspace,
49+
);
50+
}
51+
}
4352

4453
public dispose(): void {
4554
while (this.disposables.length > 0) {
@@ -56,8 +65,9 @@ export class ExtensionActivationManager implements IExtensionActivationManager {
5665
await this.initialize();
5766

5867
// Activate all activation services together.
68+
5969
await Promise.all([
60-
Promise.all(this.singleActivationServices.map((item) => item.activate())),
70+
...this.singleActivationServices.map((item) => item.activate()),
6171
this.activateWorkspace(this.activeResourceService.getActiveResource()),
6272
]);
6373
}

src/client/activation/activationService.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@ export class LanguageServerExtensionActivationService
4949

5050
private activatedServer?: IActivatedServer;
5151

52+
public readonly supportedWorkspaceTypes = { untrustedWorkspace: true, virtualWorkspace: true };
53+
5254
private readonly workspaceService: IWorkspaceService;
5355

5456
private readonly configurationService: IConfigurationService;
@@ -234,7 +236,6 @@ export class LanguageServerExtensionActivationService
234236
}
235237

236238
this.sendTelemetryForChosenLanguageServer(serverType).ignoreErrors();
237-
238239
await this.logStartup(serverType);
239240
let server = this.serviceContainer.get<ILanguageServerActivator>(ILanguageServerActivator, serverType);
240241
try {

src/client/activation/common/analysisOptions.ts

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// Licensed under the MIT License.
33
import { Disposable, Event, EventEmitter, WorkspaceFolder } from 'vscode';
44
import { DocumentFilter, LanguageClientOptions, RevealOutputChannelOn } from 'vscode-languageclient/node';
5+
import { IWorkspaceService } from '../../common/application/types';
56

67
import { PYTHON, PYTHON_LANGUAGE } from '../../common/constants';
78
import { IOutputChannel, Resource } from '../../common/types';
@@ -15,7 +16,10 @@ export abstract class LanguageServerAnalysisOptionsBase implements ILanguageServ
1516
protected readonly didChange = new EventEmitter<void>();
1617
private readonly output: IOutputChannel;
1718

18-
protected constructor(lsOutputChannel: ILanguageServerOutputChannel) {
19+
protected constructor(
20+
lsOutputChannel: ILanguageServerOutputChannel,
21+
protected readonly workspace: IWorkspaceService,
22+
) {
1923
this.output = lsOutputChannel.channel;
2024
}
2125

@@ -51,7 +55,7 @@ export abstract class LanguageServerAnalysisOptionsBase implements ILanguageServ
5155
}
5256

5357
protected getDocumentFilters(_workspaceFolder?: WorkspaceFolder): DocumentFilter[] {
54-
return PYTHON;
58+
return this.workspace.isVirtualWorkspace ? [{ language: PYTHON_LANGUAGE }] : PYTHON;
5559
}
5660

5761
protected async getInitializationOptions(): Promise<any> {
@@ -66,8 +70,9 @@ export abstract class LanguageServerAnalysisOptionsWithEnv extends LanguageServe
6670
protected constructor(
6771
private readonly envVarsProvider: IEnvironmentVariablesProvider,
6872
lsOutputChannel: ILanguageServerOutputChannel,
73+
workspace: IWorkspaceService,
6974
) {
70-
super(lsOutputChannel);
75+
super(lsOutputChannel, workspace);
7176
}
7277

7378
public async initialize(_resource: Resource, _interpreter: PythonEnvironment | undefined) {

src/client/activation/common/loadLanguageServerExtension.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ import { IExtensionSingleActivationService } from '../types';
1313

1414
@injectable()
1515
export class LoadLanguageServerExtension implements IExtensionSingleActivationService {
16+
public readonly supportedWorkspaceTypes = { untrustedWorkspace: true, virtualWorkspace: true };
17+
1618
constructor(
1719
@inject(ICommandManager) private readonly commandManager: ICommandManager,
1820
@inject(IDisposableRegistry) private readonly disposables: IDisposableRegistry,

src/client/activation/extensionSurvey.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ const WAIT_TIME_TO_SHOW_SURVEY = 1000 * 60 * 60 * 3; // 3 hours
2828

2929
@injectable()
3030
export class ExtensionSurveyPrompt implements IExtensionSingleActivationService {
31+
public readonly supportedWorkspaceTypes = { untrustedWorkspace: false, virtualWorkspace: true };
3132
constructor(
3233
@inject(IApplicationShell) private appShell: IApplicationShell,
3334
@inject(IBrowserService) private browserService: IBrowserService,

src/client/activation/jedi/analysisOptions.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,9 @@ export class JediLanguageServerAnalysisOptions extends LanguageServerAnalysisOpt
2121
@inject(IEnvironmentVariablesProvider) envVarsProvider: IEnvironmentVariablesProvider,
2222
@inject(ILanguageServerOutputChannel) lsOutputChannel: ILanguageServerOutputChannel,
2323
@inject(IConfigurationService) private readonly configurationService: IConfigurationService,
24-
@inject(IWorkspaceService) private readonly workspace: IWorkspaceService,
24+
@inject(IWorkspaceService) workspace: IWorkspaceService,
2525
) {
26-
super(envVarsProvider, lsOutputChannel);
26+
super(envVarsProvider, lsOutputChannel, workspace);
2727
this.resource = undefined;
2828
}
2929

src/client/activation/node/analysisOptions.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,18 @@
11
// Copyright (c) Microsoft Corporation. All rights reserved.
22
// Licensed under the MIT License.
33
import { inject, injectable } from 'inversify';
4+
import { IWorkspaceService } from '../../common/application/types';
45

56
import { LanguageServerAnalysisOptionsBase } from '../common/analysisOptions';
67
import { ILanguageServerOutputChannel } from '../types';
78

89
@injectable()
910
export class NodeLanguageServerAnalysisOptions extends LanguageServerAnalysisOptionsBase {
10-
constructor(@inject(ILanguageServerOutputChannel) lsOutputChannel: ILanguageServerOutputChannel) {
11-
super(lsOutputChannel);
11+
constructor(
12+
@inject(ILanguageServerOutputChannel) lsOutputChannel: ILanguageServerOutputChannel,
13+
@inject(IWorkspaceService) workspace: IWorkspaceService,
14+
) {
15+
super(lsOutputChannel, workspace);
1216
}
1317

1418
protected async getInitializationOptions() {

src/client/activation/types.ts

Lines changed: 2 additions & 0 deletions
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+
supportedWorkspaceTypes: { untrustedWorkspace: boolean; virtualWorkspace: boolean };
6162
activate(resource: Resource): Promise<void>;
6263
}
6364

@@ -178,5 +179,6 @@ export const IExtensionSingleActivationService = Symbol('IExtensionSingleActivat
178179
* @interface IExtensionSingleActivationService
179180
*/
180181
export interface IExtensionSingleActivationService {
182+
supportedWorkspaceTypes: { untrustedWorkspace: boolean; virtualWorkspace: boolean };
181183
activate(): Promise<void>;
182184
}

src/client/common/application/commands/reloadCommand.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import { IApplicationShell, ICommandManager } from '../types';
1414
*/
1515
@injectable()
1616
export class ReloadVSCodeCommandHandler implements IExtensionSingleActivationService {
17+
public readonly supportedWorkspaceTypes = { untrustedWorkspace: false, virtualWorkspace: true };
1718
constructor(
1819
@inject(ICommandManager) private readonly commandManager: ICommandManager,
1920
@inject(IApplicationShell) private readonly appShell: IApplicationShell,

src/client/common/application/commands/reportIssueCommand.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ import { EnvironmentType } from '../../../pythonEnvironments/info';
2222
*/
2323
@injectable()
2424
export class ReportIssueCommandHandler implements IExtensionSingleActivationService {
25+
public readonly supportedWorkspaceTypes = { untrustedWorkspace: false, virtualWorkspace: true };
26+
2527
constructor(
2628
@inject(ICommandManager) private readonly commandManager: ICommandManager,
2729
@inject(IWorkspaceService) private readonly workspaceService: IWorkspaceService,

src/client/common/application/debugSessionTelemetry.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ class TelemetryTracker implements DebugAdapterTracker {
6262

6363
@injectable()
6464
export class DebugSessionTelemetry implements DebugAdapterTrackerFactory, IExtensionSingleActivationService {
65+
public readonly supportedWorkspaceTypes = { untrustedWorkspace: false, virtualWorkspace: true };
6566
constructor(
6667
@inject(IDisposableRegistry) disposableRegistry: IDisposableRegistry,
6768
@inject(IDebugService) debugService: IDebugService,

src/client/common/application/types.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -729,7 +729,10 @@ export interface IWorkspaceService {
729729
* @memberof IWorkspaceService
730730
*/
731731
readonly hasWorkspaceFolders: boolean;
732-
732+
/**
733+
* Returns if we're running in a virtual workspace.
734+
*/
735+
readonly isVirtualWorkspace: boolean;
733736
/**
734737
* Returns the [workspace folder](#WorkspaceFolder) that contains a given uri.
735738
* * returns `undefined` when the given uri doesn't match any workspace folder

src/client/common/application/workspace.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,12 @@ export class WorkspaceService implements IWorkspaceService {
8383
: defaultValue;
8484
}
8585

86+
public get isVirtualWorkspace(): boolean {
87+
const isVirtualWorkspace =
88+
workspace.workspaceFolders && workspace.workspaceFolders.every((f) => f.uri.scheme !== 'file');
89+
return !!isVirtualWorkspace;
90+
}
91+
8692
private get searchExcludes() {
8793
const searchExcludes = this.getConfiguration('search.exclude');
8894
const enabledSearchExcludes = Object.keys(searchExcludes).filter((key) => searchExcludes.get(key) === true);

src/client/common/insidersBuild/insidersExtensionService.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import { traceDecoratorError } from '../../logging';
1919

2020
@injectable()
2121
export class InsidersExtensionService implements IExtensionSingleActivationService {
22+
public readonly supportedWorkspaceTypes = { untrustedWorkspace: false, virtualWorkspace: true };
2223
constructor(
2324
@inject(IExtensionChannelService) private readonly extensionChannelService: IExtensionChannelService,
2425
@inject(IInsiderExtensionPrompt) private readonly insidersPrompt: IInsiderExtensionPrompt,

src/client/common/persistentState.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ export type KeysStorage = { key: string; defaultValue: unknown };
6363

6464
@injectable()
6565
export class PersistentStateFactory implements IPersistentStateFactory, IExtensionSingleActivationService {
66+
public readonly supportedWorkspaceTypes = { untrustedWorkspace: false, virtualWorkspace: true };
6667
public readonly _globalKeysStorage = new PersistentState<KeysStorage[]>(
6768
this.globalState,
6869
GLOBAL_PERSISTENT_KEYS,

src/client/debugger/extension/adapter/activator.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import { IDebugAdapterDescriptorFactory, IDebugSessionLoggingFactory, IOutdatedD
1313

1414
@injectable()
1515
export class DebugAdapterActivator implements IExtensionSingleActivationService {
16+
public readonly supportedWorkspaceTypes = { untrustedWorkspace: false, virtualWorkspace: false };
1617
constructor(
1718
@inject(IDebugService) private readonly debugService: IDebugService,
1819
@inject(IDebugAdapterDescriptorFactory) private descriptorFactory: IDebugAdapterDescriptorFactory,

src/client/debugger/extension/configuration/launch.json/completionProvider.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ enum JsonLanguages {
2828

2929
@injectable()
3030
export class LaunchJsonCompletionProvider implements CompletionItemProvider, IExtensionSingleActivationService {
31+
public readonly supportedWorkspaceTypes = { untrustedWorkspace: false, virtualWorkspace: false };
3132
constructor(
3233
@inject(ILanguageService) private readonly languageService: ILanguageService,
3334
@inject(IDisposableRegistry) private readonly disposableRegistry: IDisposableRegistry,

src/client/debugger/extension/configuration/launch.json/interpreterPathCommand.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import { IConfigurationService, IDisposable, IDisposableRegistry } from '../../.
1212

1313
@injectable()
1414
export class InterpreterPathCommand implements IExtensionSingleActivationService {
15+
public readonly supportedWorkspaceTypes = { untrustedWorkspace: false, virtualWorkspace: false };
1516
constructor(
1617
@inject(ICommandManager) private readonly commandManager: ICommandManager,
1718
@inject(IConfigurationService) private readonly configurationService: IConfigurationService,

src/client/debugger/extension/configuration/launch.json/updaterService.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,7 @@ export class LaunchJsonUpdaterServiceHelper {
146146

147147
@injectable()
148148
export class LaunchJsonUpdaterService implements IExtensionSingleActivationService {
149+
public readonly supportedWorkspaceTypes = { untrustedWorkspace: false, virtualWorkspace: false };
149150
constructor(
150151
@inject(ICommandManager) private readonly commandManager: ICommandManager,
151152
@inject(IDisposableRegistry) private readonly disposableRegistry: IDisposableRegistry,

src/client/debugger/extension/debugCommands.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ import { DebugPurpose, LaunchRequestArguments } from '../types';
1515

1616
@injectable()
1717
export class DebugCommands implements IExtensionSingleActivationService {
18+
public readonly supportedWorkspaceTypes = { untrustedWorkspace: false, virtualWorkspace: false };
19+
1820
constructor(
1921
@inject(ICommandManager) private readonly commandManager: ICommandManager,
2022
@inject(IDebugService) private readonly debugService: IDebugService,

src/client/extension.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ export async function activate(context: IExtensionContext): Promise<IExtensionAp
6868
}
6969
// Send the "success" telemetry only if activation did not fail.
7070
// Otherwise Telemetry is send via the error handler.
71+
7172
sendStartupTelemetry(ready, durations, stopWatch, serviceContainer)
7273
// Run in the background.
7374
.ignoreErrors();
@@ -131,8 +132,8 @@ async function activateUnsafe(
131132

132133
setTimeout(async () => {
133134
if (activatedServiceContainer) {
134-
const interpreterManager = activatedServiceContainer.get<IInterpreterService>(IInterpreterService);
135135
const workspaceService = activatedServiceContainer.get<IWorkspaceService>(IWorkspaceService);
136+
const interpreterManager = activatedServiceContainer.get<IInterpreterService>(IInterpreterService);
136137
const workspaces = workspaceService.workspaceFolders ?? [];
137138
await interpreterManager
138139
.refresh(workspaces.length > 0 ? workspaces[0].uri : undefined)
@@ -159,6 +160,7 @@ async function handleError(ex: Error, startupDurations: IStartupDurations) {
159160
"Extension activation failed, run the 'Developer: Toggle Developer Tools' command for more information.",
160161
);
161162
traceError('extension activation failed', ex);
163+
162164
await sendErrorTelemetry(ex, startupDurations, activatedServiceContainer);
163165
}
164166

0 commit comments

Comments
 (0)