Skip to content

Commit 8e3f522

Browse files
authored
Display a notification when using JediLSP with Python 2.7 (#17407)
* 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 * Add diagnostic * Add tests * Run diagnostic in the background * Remove manual diagnostic handling * Localize "do not show again"
1 parent 7f230ca commit 8e3f522

File tree

9 files changed

+490
-213
lines changed

9 files changed

+490
-213
lines changed

package.nls.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,7 @@
201201
"products.installingModule": "Installing {0}",
202202
"OutdatedDebugger.updateDebuggerMessage": "We noticed you are attaching to ptvsd (Python debugger), which was deprecated on May 1st, 2020. Please switch to [debugpy](https://aka.ms/migrateToDebugpy).",
203203
"Python27Support.bannerMessage": "The Python extension will have limited support for Python 2.7 starting in the next release, due to changes in external projects we rely on. [Learn more](https://aka.ms/python-27-support).",
204+
"Python27Support.jediMessage": "IntelliSense with Jedi for Python 2.7 is no longer supported. [Learn more](https://aka.ms/python-27-support).",
204205
"Jupyter.extensionRequired": "The Jupyter extension is required to perform that task. Click Yes to open the Jupyter extension installation page.",
205206
"TensorBoard.missingSourceFile": "We could not locate the requested source file on disk. Please manually specify the file.",
206207
"TensorBoard.selectMissingSourceFile": "Choose File",

src/client/activation/activationService.ts

Lines changed: 1 addition & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,7 @@
33
import '../common/extensions';
44

55
import { inject, injectable } from 'inversify';
6-
import { ConfigurationChangeEvent, ConfigurationTarget, Disposable, OutputChannel, Uri } from 'vscode';
7-
6+
import { ConfigurationChangeEvent, Disposable, OutputChannel, Uri } from 'vscode';
87
import { LSNotSupportedDiagnosticServiceId } from '../application/diagnostics/checks/lsNotSupported';
98
import { IDiagnosticsService } from '../application/diagnostics/types';
109
import { IApplicationShell, ICommandManager, IWorkspaceService } from '../common/application/types';
@@ -232,8 +231,6 @@ export class LanguageServerExtensionActivationService
232231
): Promise<RefCountedLanguageServer> {
233232
let serverType = this.getCurrentLanguageServerType();
234233

235-
this.updateLanguageServerSetting(resource);
236-
237234
if (serverType === LanguageServerType.Microsoft) {
238235
const lsNotSupportedDiagnosticService = this.serviceContainer.get<IDiagnosticsService>(
239236
IDiagnosticsService,
@@ -345,23 +342,4 @@ export class LanguageServerExtensionActivationService
345342
const values = await Promise.all([...this.cache.values()]);
346343
values.forEach((v) => (v.clearAnalysisCache ? v.clearAnalysisCache() : noop()));
347344
}
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-
}
367345
}
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
/* eslint-disable max-classes-per-file */
2+
// Copyright (c) Microsoft Corporation. All rights reserved.
3+
// Licensed under the MIT License.
4+
5+
import { inject, named } from 'inversify';
6+
import { ConfigurationTarget, DiagnosticSeverity } from 'vscode';
7+
import { LanguageServerType } from '../../../activation/types';
8+
import { IWorkspaceService } from '../../../common/application/types';
9+
import { IConfigurationService, IDisposableRegistry, Resource } from '../../../common/types';
10+
import { Common, Python27Support } from '../../../common/utils/localize';
11+
import { IInterpreterService } from '../../../interpreter/contracts';
12+
import { IServiceContainer } from '../../../ioc/types';
13+
import { BaseDiagnostic, BaseDiagnosticsService } from '../base';
14+
import { IDiagnosticsCommandFactory } from '../commands/types';
15+
import { DiagnosticCodes } from '../constants';
16+
import { DiagnosticCommandPromptHandlerServiceId, MessageCommandPrompt } from '../promptHandler';
17+
import { DiagnosticScope, IDiagnostic, IDiagnosticHandlerService } from '../types';
18+
19+
export class JediPython27NotSupportedDiagnostic extends BaseDiagnostic {
20+
constructor(message: string, resource: Resource) {
21+
super(
22+
DiagnosticCodes.JediPython27NotSupportedDiagnostic,
23+
message,
24+
DiagnosticSeverity.Warning,
25+
DiagnosticScope.Global,
26+
resource,
27+
);
28+
}
29+
}
30+
31+
export const JediPython27NotSupportedDiagnosticServiceId = 'JediPython27NotSupportedDiagnosticServiceId';
32+
33+
export class JediPython27NotSupportedDiagnosticService extends BaseDiagnosticsService {
34+
constructor(
35+
@inject(IServiceContainer) serviceContainer: IServiceContainer,
36+
@inject(IInterpreterService) private readonly interpreterService: IInterpreterService,
37+
@inject(IWorkspaceService) private readonly workspaceService: IWorkspaceService,
38+
@inject(IConfigurationService) private readonly configurationService: IConfigurationService,
39+
@inject(IDiagnosticHandlerService)
40+
@named(DiagnosticCommandPromptHandlerServiceId)
41+
protected readonly messageService: IDiagnosticHandlerService<MessageCommandPrompt>,
42+
@inject(IDisposableRegistry) disposableRegistry: IDisposableRegistry,
43+
) {
44+
super([DiagnosticCodes.JediPython27NotSupportedDiagnostic], serviceContainer, disposableRegistry, true);
45+
}
46+
47+
public async diagnose(resource: Resource): Promise<IDiagnostic[]> {
48+
const interpreter = await this.interpreterService.getActiveInterpreter(resource);
49+
50+
if (interpreter && (interpreter.version?.major ?? 0) < 3) {
51+
return [new JediPython27NotSupportedDiagnostic(Python27Support.jediMessage(), resource)];
52+
}
53+
54+
return [];
55+
}
56+
57+
protected async onHandle(diagnostics: IDiagnostic[]): Promise<void> {
58+
if (diagnostics.length === 0 || !this.canHandle(diagnostics[0])) {
59+
return;
60+
}
61+
const diagnostic = diagnostics[0];
62+
if (await this.filterService.shouldIgnoreDiagnostic(diagnostic.code)) {
63+
return;
64+
}
65+
66+
this.updateLanguageServerSetting(diagnostic.resource);
67+
68+
const commandFactory = this.serviceContainer.get<IDiagnosticsCommandFactory>(IDiagnosticsCommandFactory);
69+
const options = [
70+
{
71+
prompt: Common.gotIt(),
72+
},
73+
{
74+
prompt: Common.doNotShowAgain(),
75+
command: commandFactory.createCommand(diagnostic, { type: 'ignore', options: DiagnosticScope.Global }),
76+
},
77+
];
78+
79+
await this.messageService.handle(diagnostic, { commandPrompts: options });
80+
}
81+
82+
private updateLanguageServerSetting(resource: Resource): void {
83+
// Update settings.json value to Jedi if it's JediLSP.
84+
const settings = this.workspaceService
85+
.getConfiguration('python', resource)
86+
.inspect<LanguageServerType>('languageServer');
87+
88+
let configTarget: ConfigurationTarget;
89+
90+
if (settings?.workspaceValue === LanguageServerType.JediLSP) {
91+
configTarget = ConfigurationTarget.Workspace;
92+
} else if (settings?.globalValue === LanguageServerType.JediLSP) {
93+
configTarget = ConfigurationTarget.Global;
94+
} else {
95+
return;
96+
}
97+
98+
this.configurationService.updateSetting('languageServer', LanguageServerType.Jedi, resource, configTarget);
99+
}
100+
}

src/client/application/diagnostics/constants.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,4 +21,5 @@ export enum DiagnosticCodes {
2121
UpgradeCodeRunnerDiagnostic = 'UpgradeCodeRunnerDiagnostic',
2222
PylanceDefaultDiagnostic = 'PylanceDefaultDiagnostic',
2323
MPLSSurveyDiagnostic = 'MPLSSurveyDiagnostic',
24+
JediPython27NotSupportedDiagnostic = 'JediPython27NotSupportedDiagnostic',
2425
}

src/client/application/diagnostics/serviceRegistry.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,10 @@ import {
1919
InvalidPythonPathInDebuggerService,
2020
InvalidPythonPathInDebuggerServiceId,
2121
} from './checks/invalidPythonPathInDebugger';
22+
import {
23+
JediPython27NotSupportedDiagnosticService,
24+
JediPython27NotSupportedDiagnosticServiceId,
25+
} from './checks/jediPython27NotSupported';
2226
import { LSNotSupportedDiagnosticService, LSNotSupportedDiagnosticServiceId } from './checks/lsNotSupported';
2327
import {
2428
InvalidMacPythonInterpreterService,
@@ -100,6 +104,12 @@ export function registerTypes(serviceManager: IServiceManager, languageServerTyp
100104
PylanceDefaultDiagnosticServiceId,
101105
);
102106

107+
serviceManager.addSingleton<IDiagnosticsService>(
108+
IDiagnosticsService,
109+
JediPython27NotSupportedDiagnosticService,
110+
JediPython27NotSupportedDiagnosticServiceId,
111+
);
112+
103113
serviceManager.addSingleton<IDiagnosticsCommandFactory>(IDiagnosticsCommandFactory, DiagnosticsCommandFactory);
104114
serviceManager.addSingleton<IApplicationDiagnostics>(IApplicationDiagnostics, ApplicationDiagnostics);
105115

src/client/common/utils/localize.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -548,6 +548,11 @@ export namespace Python27Support {
548548
'Python27Support.bannerMessage',
549549
'The Python extension will have limited support for Python 2.7 starting in the next release, due to changes in external projects we rely on. [Learn more](https://aka.ms/python-27-support).',
550550
);
551+
552+
export const jediMessage = localize(
553+
'Python27Support.jediMessage',
554+
'IntelliSense with Jedi for Python 2.7 is no longer supported. [Learn more](https://aka.ms/python-27-support).',
555+
);
551556
}
552557

553558
export namespace MPLSDeprecation {

0 commit comments

Comments
 (0)