Skip to content

Commit 862a88d

Browse files
authored
Replace Jedi with Jedi LSP (#17273)
* Remove the experiment * News file * Fix linting issue * Turn JediLSP option into Jedi * Remove commented code * Update comment * Always register no LS activator * Add basic 2.7 LS support (Pylance or None) * Skip tests on Python 2.7 * Fix unit tests * Default to Pylance * Fix unit tests * Set default LS to Jedi * Install JediLSP requirements for testing * Change default back to none * Typo * Turn condition around to match comment * Remove JediLSP requirements * Default to None * Install JediLSP requirements * Install JediLSP reqs for smoke tests too * Install JediLSP reqs in coverage step * Undo PR check workflow changes * Turns out it won't run if there's no 'run' keyword * Change condition order * Add activation service unit tests * Remove comment * Add NoLanguageServerExtensionActivator check * Delete Jedi tests * Change condition order * Install Jedi LSP reqs in nightly coverage
1 parent 7e64fb4 commit 862a88d

33 files changed

+420
-2535
lines changed

.github/workflows/nightly-coverage.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ jobs:
5151
python -m pip --disable-pip-version-check install -t ./pythonFiles/lib/python --no-cache-dir --implementation py --no-deps --upgrade -r requirements.txt --no-user
5252
# We need to have debugpy so that tests relying on it keep passing, but we don't need install_debugpy's logic in the test phase.
5353
python -m pip --disable-pip-version-check install -t ./pythonFiles/lib/python --no-cache-dir --implementation py --no-deps --upgrade --pre debugpy
54+
python -m pip --disable-pip-version-check install -t ./pythonFiles/lib/jedilsp --no-cache-dir --implementation py --no-deps --upgrade -r ./jedils_requirements.txt
5455
5556
- name: Install test requirements
5657
run: python -m pip install --upgrade -r build/test-requirements.txt

.github/workflows/pr-check.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,10 @@ jobs:
100100
# We need to have debugpy so that tests relying on it keep passing, but we don't need install_debugpy's logic in the test phase.
101101
python -m pip --disable-pip-version-check install -t ./pythonFiles/lib/python --no-cache-dir --implementation py --no-deps --upgrade --pre debugpy
102102
103+
- name: Install Jedi LSP requirements
104+
run: python -m pip --disable-pip-version-check install -t ./pythonFiles/lib/jedilsp --no-cache-dir --implementation py --no-deps --upgrade -r ./jedils_requirements.txt
105+
if: startsWith(matrix.python, 3.)
106+
103107
- name: Install test requirements
104108
run: python -m pip install --upgrade -r build/test-requirements.txt
105109

@@ -388,6 +392,7 @@ jobs:
388392
python -m pip --disable-pip-version-check install -t ./pythonFiles/lib/python --no-cache-dir --implementation py --no-deps --upgrade -r requirements.txt --no-user
389393
# We need to have debugpy so that tests relying on it keep passing, but we don't need install_debugpy's logic in the test phase.
390394
python -m pip --disable-pip-version-check install -t ./pythonFiles/lib/python --no-cache-dir --implementation py --no-deps --upgrade --pre debugpy
395+
python -m pip --disable-pip-version-check install -t ./pythonFiles/lib/jedilsp --no-cache-dir --implementation py --no-deps --upgrade -r ./jedils_requirements.txt
391396
392397
- name: Install test requirements
393398
run: python -m pip install --upgrade -r build/test-requirements.txt

news/1 Enhancements/11995.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Phase out Jedi 0.17, and use Jedi behind a language server protocol as the Jedi option.

package.json

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -645,7 +645,6 @@
645645
"pythonDeprecatePythonPath",
646646
"pythonDiscoveryModule",
647647
"pythonDiscoveryModuleWithoutWatcher",
648-
"pythonJediLSP",
649648
"pythonSortEnvs",
650649
"pythonSurveyNotification",
651650
"pythonTensorboardExperiment",
@@ -666,7 +665,6 @@
666665
"pythonDeprecatePythonPath",
667666
"pythonDiscoveryModule",
668667
"pythonDiscoveryModuleWithoutWatcher",
669-
"pythonJediLSP",
670668
"pythonSortEnvs",
671669
"pythonSurveyNotification",
672670
"pythonTensorboardExperiment",
@@ -770,13 +768,11 @@
770768
"enum": [
771769
"Default",
772770
"Jedi",
773-
"JediLSP",
774771
"Pylance",
775772
"None"
776773
],
777774
"enumDescriptions": [
778775
"Automatically select a language server: Pylance if installed and available, otherwise fallback to Jedi.",
779-
"Use Jedi as a language server.",
780776
"Use Jedi behind the Language Server Protocol (LSP) as a language server.",
781777
"Use Pylance as a language server.",
782778
"Disable language server capabilities."

src/client/activation/activationService.ts

Lines changed: 35 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import '../common/extensions';
44

55
import { inject, injectable } from 'inversify';
6-
import { ConfigurationChangeEvent, Disposable, OutputChannel, Uri } from 'vscode';
6+
import { ConfigurationChangeEvent, ConfigurationTarget, Disposable, OutputChannel, Uri } from 'vscode';
77

88
import { LSNotSupportedDiagnosticServiceId } from '../application/diagnostics/checks/lsNotSupported';
99
import { IDiagnosticsService } from '../application/diagnostics/types';
@@ -56,6 +56,8 @@ export class LanguageServerExtensionActivationService
5656

5757
private readonly workspaceService: IWorkspaceService;
5858

59+
private readonly configurationService: IConfigurationService;
60+
5961
private readonly output: OutputChannel;
6062

6163
private readonly interpreterService: IInterpreterService;
@@ -69,6 +71,7 @@ export class LanguageServerExtensionActivationService
6971
@inject(IPersistentStateFactory) private stateFactory: IPersistentStateFactory,
7072
) {
7173
this.workspaceService = this.serviceContainer.get<IWorkspaceService>(IWorkspaceService);
74+
this.configurationService = this.serviceContainer.get<IConfigurationService>(IConfigurationService);
7275
this.interpreterService = this.serviceContainer.get<IInterpreterService>(IInterpreterService);
7376
this.output = this.serviceContainer.get<OutputChannel>(IOutputChannel, STANDARD_OUTPUT_CHANNEL);
7477

@@ -87,8 +90,8 @@ export class LanguageServerExtensionActivationService
8790
this.serviceContainer.get<IExtensions>(IExtensions),
8891
this.serviceContainer.get<IApplicationShell>(IApplicationShell),
8992
this.serviceContainer.get<ICommandManager>(ICommandManager),
90-
this.serviceContainer.get<IWorkspaceService>(IWorkspaceService),
91-
this.serviceContainer.get<IConfigurationService>(IConfigurationService),
93+
this.workspaceService,
94+
this.configurationService,
9295
);
9396
disposables.push(this.languageServerChangeHandler);
9497
}
@@ -228,6 +231,9 @@ export class LanguageServerExtensionActivationService
228231
key: string,
229232
): Promise<RefCountedLanguageServer> {
230233
let serverType = this.getCurrentLanguageServerType();
234+
235+
this.updateLanguageServerSetting(resource);
236+
231237
if (serverType === LanguageServerType.Microsoft) {
232238
const lsNotSupportedDiagnosticService = this.serviceContainer.get<IDiagnosticsService>(
233239
IDiagnosticsService,
@@ -243,22 +249,13 @@ export class LanguageServerExtensionActivationService
243249
}
244250
}
245251

246-
if (serverType === LanguageServerType.JediLSP && interpreter && interpreter.version) {
247-
if (interpreter.version.major < 3 || (interpreter.version.major === 3 && interpreter.version.minor < 6)) {
248-
sendTelemetryEvent(EventName.JEDI_FALLBACK);
249-
serverType = LanguageServerType.Jedi;
250-
}
251-
}
252-
253-
// If Pylance was chosen via the default and the interpreter is Python 2, fall back to
254-
// Jedi. If Pylance was explicitly chosen, continue anyway, even if Pylance won't work
255-
// as expected, matching pre-default behavior.
256-
if (this.getCurrentLanguageServerTypeIsDefault()) {
257-
if (serverType === LanguageServerType.Node && interpreter && interpreter.version) {
258-
if (interpreter.version.major < 3) {
259-
sendTelemetryEvent(EventName.JEDI_FALLBACK);
260-
serverType = LanguageServerType.Jedi;
261-
}
252+
// If the interpreter is Python 2 and the LS setting is explicitly set to Jedi, turn it off.
253+
// If set to Default, use Pylance.
254+
if (interpreter && (interpreter.version?.major ?? 0) < 3) {
255+
if (serverType === LanguageServerType.Jedi) {
256+
serverType = LanguageServerType.None;
257+
} else if (this.getCurrentLanguageServerTypeIsDefault()) {
258+
serverType = LanguageServerType.Node;
262259
}
263260
}
264261

@@ -348,4 +345,23 @@ export class LanguageServerExtensionActivationService
348345
const values = await Promise.all([...this.cache.values()]);
349346
values.forEach((v) => (v.clearAnalysisCache ? v.clearAnalysisCache() : noop()));
350347
}
348+
349+
private updateLanguageServerSetting(resource: Resource): void {
350+
// Update settings.json value to Jedi if it's JediLSP.
351+
const settings = this.workspaceService
352+
.getConfiguration('python', resource)
353+
.inspect<LanguageServerType>('languageServer');
354+
355+
let configTarget: ConfigurationTarget;
356+
357+
if (settings?.workspaceValue === LanguageServerType.JediLSP) {
358+
configTarget = ConfigurationTarget.Workspace;
359+
} else if (settings?.globalValue === LanguageServerType.JediLSP) {
360+
configTarget = ConfigurationTarget.Global;
361+
} else {
362+
return;
363+
}
364+
365+
this.configurationService.updateSetting('languageServer', LanguageServerType.Jedi, resource, configTarget);
366+
}
351367
}

src/client/activation/common/defaultlanguageServer.ts

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,7 @@
33

44
import { injectable } from 'inversify';
55
import { PYLANCE_EXTENSION_ID } from '../../common/constants';
6-
import { JediLSP } from '../../common/experiments/groups';
7-
import { IDefaultLanguageServer, IExperimentService, IExtensions, DefaultLSType } from '../../common/types';
6+
import { IDefaultLanguageServer, IExtensions, DefaultLSType } from '../../common/types';
87
import { IServiceManager } from '../../ioc/types';
98
import { ILSExtensionApi } from '../node/languageServerFolderService';
109
import { LanguageServerType } from '../types';
@@ -19,26 +18,20 @@ class DefaultLanguageServer implements IDefaultLanguageServer {
1918
}
2019

2120
export async function setDefaultLanguageServer(
22-
experimentService: IExperimentService,
2321
extensions: IExtensions,
2422
serviceManager: IServiceManager,
2523
): Promise<void> {
26-
const lsType = await getDefaultLanguageServer(experimentService, extensions);
24+
const lsType = await getDefaultLanguageServer(extensions);
2725
serviceManager.addSingletonInstance<IDefaultLanguageServer>(
2826
IDefaultLanguageServer,
2927
new DefaultLanguageServer(lsType),
3028
);
3129
}
3230

33-
async function getDefaultLanguageServer(
34-
experimentService: IExperimentService,
35-
extensions: IExtensions,
36-
): Promise<DefaultLSType> {
31+
async function getDefaultLanguageServer(extensions: IExtensions): Promise<DefaultLSType> {
3732
if (extensions.getExtension<ILSExtensionApi>(PYLANCE_EXTENSION_ID)) {
3833
return LanguageServerType.Node;
3934
}
4035

41-
return (await experimentService.inExperiment(JediLSP.experiment))
42-
? LanguageServerType.JediLSP
43-
: LanguageServerType.Jedi;
36+
return LanguageServerType.Jedi;
4437
}

src/client/activation/jedi/manager.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ export class JediLanguageServerManager implements ILanguageServerManager {
4545
constructor(
4646
@inject(IServiceContainer) private readonly serviceContainer: IServiceContainer,
4747
@inject(ILanguageServerAnalysisOptions)
48-
@named(LanguageServerType.JediLSP)
48+
@named(LanguageServerType.Jedi)
4949
private readonly analysisOptions: ILanguageServerAnalysisOptions,
5050
@inject(ICommandManager) commandManager: ICommandManager,
5151
) {
@@ -144,7 +144,7 @@ export class JediLanguageServerManager implements ILanguageServerManager {
144144
const options = await this.analysisOptions.getAnalysisOptions();
145145
this.middleware = new LanguageClientMiddleware(
146146
this.serviceContainer,
147-
LanguageServerType.JediLSP,
147+
LanguageServerType.Jedi,
148148
() => this.languageServerProxy?.languageClient,
149149
this.lsVersion,
150150
);

src/client/activation/languageClientMiddleware.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ export class LanguageClientMiddleware extends LanguageClientMiddlewareBase {
2424
) {
2525
super(serviceContainer, serverType, sendTelemetryEvent, serverVersion);
2626

27-
if (serverType === LanguageServerType.None || serverType === LanguageServerType.Jedi) {
27+
if (serverType === LanguageServerType.None) {
2828
return;
2929
}
3030

src/client/activation/languageClientMiddlewareBase.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ export class LanguageClientMiddlewareBase implements Middleware {
133133
this.eventName = EventName.PYTHON_LANGUAGE_SERVER_REQUEST;
134134
} else if (serverType === LanguageServerType.Node) {
135135
this.eventName = EventName.LANGUAGE_SERVER_REQUEST;
136-
} else if (serverType === LanguageServerType.JediLSP) {
136+
} else if (serverType === LanguageServerType.Jedi) {
137137
this.eventName = EventName.JEDI_LANGUAGE_SERVER_REQUEST;
138138
}
139139
}

src/client/activation/languageServer/deprecationPrompt.ts

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -103,10 +103,7 @@ export class MPLSDeprecationPrompt implements IMPLSDeprecationPrompt {
103103
}
104104

105105
private async switchLanguageServer(lsType: LanguageServerType.Node | LanguageServerType.Jedi): Promise<void> {
106-
let defaultType = this.defaultLanguageServer.defaultLSType;
107-
if (defaultType === LanguageServerType.JediLSP) {
108-
defaultType = LanguageServerType.Jedi;
109-
}
106+
const defaultType = this.defaultLanguageServer.defaultLSType;
110107

111108
// If changing to the default, unset the setting instead of explicitly setting it.
112109
const changeTo = lsType !== defaultType ? lsType : undefined;

src/client/activation/serviceRegistry.ts

Lines changed: 7 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ import { DownloadBetaChannelRule, DownloadDailyChannelRule } from './common/down
1010
import { LanguageServerDownloader } from './common/downloader';
1111
import { LanguageServerDownloadChannel } from './common/packageRepository';
1212
import { ExtensionSurveyPrompt } from './extensionSurvey';
13-
import { JediExtensionActivator } from './jedi';
1413
import { JediLanguageServerAnalysisOptions } from './jedi/analysisOptions';
1514
import { JediLanguageClientFactory } from './jedi/languageClientFactory';
1615
import { JediLanguageServerProxy } from './jedi/languageServerProxy';
@@ -130,34 +129,29 @@ export function registerTypes(serviceManager: IServiceManager, languageServerTyp
130129
ILanguageServerFolderService,
131130
NodeLanguageServerFolderService,
132131
);
133-
} else if (languageServerType === LanguageServerType.JediLSP) {
132+
} else if (languageServerType === LanguageServerType.Jedi) {
134133
serviceManager.add<ILanguageServerActivator>(
135134
ILanguageServerActivator,
136135
JediLanguageServerActivator,
137-
LanguageServerType.JediLSP,
136+
LanguageServerType.Jedi,
138137
);
139138

140139
serviceManager.add<ILanguageServerAnalysisOptions>(
141140
ILanguageServerAnalysisOptions,
142141
JediLanguageServerAnalysisOptions,
143-
LanguageServerType.JediLSP,
142+
LanguageServerType.Jedi,
144143
);
145144

146145
serviceManager.addSingleton<ILanguageClientFactory>(ILanguageClientFactory, JediLanguageClientFactory);
147146
serviceManager.add<ILanguageServerManager>(ILanguageServerManager, JediLanguageServerManager);
148147
serviceManager.add<ILanguageServerProxy>(ILanguageServerProxy, JediLanguageServerProxy);
149-
} else if (languageServerType === LanguageServerType.None) {
150-
serviceManager.add<ILanguageServerActivator>(
151-
ILanguageServerActivator,
152-
NoLanguageServerExtensionActivator,
153-
LanguageServerType.None,
154-
);
155148
}
149+
156150
serviceManager.add<ILanguageServerActivator>(
157151
ILanguageServerActivator,
158-
JediExtensionActivator,
159-
LanguageServerType.Jedi,
160-
); // We fallback to Jedi if for some reason we're unable to use other language servers, hence register this always.
152+
NoLanguageServerExtensionActivator,
153+
LanguageServerType.None,
154+
);
161155

162156
serviceManager.addSingleton<IDownloadChannelRule>(
163157
IDownloadChannelRule,

src/client/common/configSettings.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -293,8 +293,12 @@ export class PythonSettings implements IPythonSettings {
293293
userLS === 'Default' ||
294294
!Object.values(LanguageServerType).includes(userLS as LanguageServerType)
295295
) {
296-
this.languageServer = this.defaultLS?.defaultLSType ?? LanguageServerType.Jedi;
296+
this.languageServer = this.defaultLS?.defaultLSType ?? LanguageServerType.None;
297297
this.languageServerIsDefault = true;
298+
} else if (userLS === 'JediLSP') {
299+
// Switch JediLSP option to Jedi.
300+
this.languageServer = LanguageServerType.Jedi;
301+
this.languageServerIsDefault = false;
298302
} else {
299303
this.languageServer = userLS as LanguageServerType;
300304
this.languageServerIsDefault = false;

src/client/common/experiments/groups.ts

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,6 @@ export enum DeprecatePythonPath {
1010
experiment = 'pythonDeprecatePythonPath',
1111
}
1212

13-
// Experiment to switch Jedi to use an LSP instead of direct providers
14-
export enum JediLSP {
15-
experiment = 'pythonJediLSP',
16-
}
1713
// Experiment to show a prompt asking users to join python mailing list.
1814
export enum JoinMailingListPromptVariants {
1915
variant1 = 'pythonJoinMailingListVar1',

src/client/common/types.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -547,7 +547,7 @@ export interface IInterpreterPathProxyService {
547547
get(resource: Resource): string;
548548
}
549549

550-
export type DefaultLSType = LanguageServerType.Jedi | LanguageServerType.JediLSP | LanguageServerType.Node;
550+
export type DefaultLSType = LanguageServerType.Jedi | LanguageServerType.Node;
551551

552552
/**
553553
* Interface used to retrieve the default language server.

src/client/extensionActivation.ts

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,7 @@ import { IApplicationEnvironment, ICommandManager } from './common/application/t
1414
import { Commands, PYTHON, PYTHON_LANGUAGE, STANDARD_OUTPUT_CHANNEL, UseProposedApi } from './common/constants';
1515
import { registerTypes as installerRegisterTypes } from './common/installer/serviceRegistry';
1616
import { IFileSystem } from './common/platform/types';
17-
import {
18-
IConfigurationService,
19-
IDisposableRegistry,
20-
IExperimentService,
21-
IExtensions,
22-
IOutputChannel,
23-
} from './common/types';
17+
import { IConfigurationService, IDisposableRegistry, IExtensions, IOutputChannel } from './common/types';
2418
import { noop } from './common/utils/misc';
2519
import { DebuggerTypeName } from './debugger/constants';
2620
import { DebugSessionEventDispatcher } from './debugger/extension/hooks/eventHandlerDispatcher';
@@ -117,10 +111,8 @@ async function activateLegacy(ext: ExtensionState): Promise<ActivationResult> {
117111
debugConfigurationRegisterTypes(serviceManager);
118112
tensorBoardRegisterTypes(serviceManager);
119113

120-
const experimentService = serviceContainer.get<IExperimentService>(IExperimentService);
121-
122114
const extensions = serviceContainer.get<IExtensions>(IExtensions);
123-
await setDefaultLanguageServer(experimentService, extensions, serviceManager);
115+
await setDefaultLanguageServer(extensions, serviceManager);
124116

125117
const configuration = serviceManager.get<IConfigurationService>(IConfigurationService);
126118
// We should start logging using the log level as soon as possible, so set it as soon as we can access the level.

src/client/jupyter/jupyterIntegration.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,7 @@ export class JupyterExtensionIntegration {
212212
const interpreter = !isResource(r) ? r : undefined;
213213
const client = await this.languageServerCache.get(resource, interpreter);
214214

215-
// Some language servers don't support the connection yet. (like Jedi until we switch to LSP)
215+
// Some language servers don't support the connection yet.
216216
if (client && client.connection && client.capabilities) {
217217
return {
218218
connection: client.connection,

0 commit comments

Comments
 (0)