Skip to content

Commit f00e21b

Browse files
authored
Set python.pythonPath in workspace/configuration LSP call (#11084)
* Set python.pythonPath in workspace/configuration LSP call * Add news * Check for undefined in isThenable * PR feedback * Grammar * Grammar2
1 parent 3a29293 commit f00e21b

File tree

5 files changed

+65
-8
lines changed

5 files changed

+65
-8
lines changed

news/1 Enhancements/11083.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Ensure the language server can query pythonPath when in the Deprecate PythonPath experiment.

src/client/activation/languageClientMiddleware.ts

Lines changed: 50 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,10 @@ import {
3131
WorkspaceEdit
3232
} from 'vscode';
3333
import {
34+
ConfigurationParams,
35+
ConfigurationRequest,
3436
HandleDiagnosticsSignature,
37+
HandlerResult,
3538
Middleware,
3639
PrepareRenameSignature,
3740
ProvideCodeActionsSignature,
@@ -51,13 +54,14 @@ import {
5154
ProvideWorkspaceSymbolsSignature,
5255
ResolveCodeLensSignature,
5356
ResolveCompletionItemSignature,
54-
ResolveDocumentLinkSignature
57+
ResolveDocumentLinkSignature,
58+
ResponseError
5559
} from 'vscode-languageclient';
5660

5761
import { ProvideDeclarationSignature } from 'vscode-languageclient/lib/declaration';
5862
import { HiddenFilePrefix } from '../common/constants';
5963
import { CollectLSRequestTiming, CollectNodeLSRequestTiming } from '../common/experimentGroups';
60-
import { IExperimentsManager, IPythonExtensionBanner } from '../common/types';
64+
import { IConfigurationService, IExperimentsManager, IPythonExtensionBanner } from '../common/types';
6165
import { StopWatch } from '../common/utils/stopWatch';
6266
import { sendTelemetryEvent } from '../telemetry';
6367
import { EventName } from '../telemetry/constants';
@@ -80,11 +84,48 @@ export class LanguageClientMiddleware implements Middleware {
8084
public nextWindow: number = 0;
8185
public eventCount: number = 0;
8286

87+
public workspace = {
88+
// tslint:disable:no-any
89+
configuration: (
90+
params: ConfigurationParams,
91+
token: CancellationToken,
92+
next: ConfigurationRequest.HandlerSignature
93+
): HandlerResult<any[], void> => {
94+
// Hand-collapse "Thenable<A> | Thenable<B> | Thenable<A|B>" into just "Thenable<A|B>" to make TS happy.
95+
const result: any[] | ResponseError<void> | Thenable<any[] | ResponseError<void>> = next(params, token);
96+
97+
// For backwards compatibility, set python.pythonPath to the configured
98+
// value as though it were in the user's settings.json file.
99+
const addPythonPath = (settings: any[] | ResponseError<void>) => {
100+
if (settings instanceof ResponseError) {
101+
return settings;
102+
}
103+
104+
params.items.forEach((item, i) => {
105+
if (item.section === 'python') {
106+
const uri = item.scopeUri ? Uri.parse(item.scopeUri) : undefined;
107+
settings[i].pythonPath = this.configService.getSettings(uri).pythonPath;
108+
}
109+
});
110+
111+
return settings;
112+
};
113+
114+
if (isThenable(result)) {
115+
return result.then(addPythonPath);
116+
}
117+
118+
return addPythonPath(result);
119+
}
120+
// tslint:enable:no-any
121+
};
122+
83123
private connected = false; // Default to not forwarding to VS code.
84124

85125
public constructor(
86126
private readonly surveyBanner: IPythonExtensionBanner,
87127
experimentsManager: IExperimentsManager,
128+
private readonly configService: IConfigurationService,
88129
serverType: LanguageServerType,
89130
public readonly serverVersion?: string
90131
) {
@@ -413,8 +454,8 @@ function captureTelemetryForLSPMethod(method: string, debounceMilliseconds: numb
413454
const result = originalMethod.apply(this, args);
414455

415456
// tslint:disable-next-line:no-unsafe-any
416-
if (result && typeof result.then === 'function') {
417-
(result as Thenable<void>).then(() => {
457+
if (result && isThenable<void>(result)) {
458+
result.then(() => {
418459
sendTelemetryEvent(eventName, stopWatch.elapsedTime, properties);
419460
});
420461
} else {
@@ -427,3 +468,8 @@ function captureTelemetryForLSPMethod(method: string, debounceMilliseconds: numb
427468
return descriptor;
428469
};
429470
}
471+
472+
// tslint:disable-next-line: no-any
473+
function isThenable<T>(v: any): v is Thenable<T> {
474+
return typeof v?.then === 'function';
475+
}

src/client/activation/languageServer/manager.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { inject, injectable, named } from 'inversify';
77
import { traceDecorators } from '../../common/logger';
88
import {
99
BANNER_NAME_LS_SURVEY,
10+
IConfigurationService,
1011
IDisposable,
1112
IExperimentsManager,
1213
IPythonExtensionBanner,
@@ -43,7 +44,8 @@ export class DotNetLanguageServerManager implements ILanguageServerManager {
4344
@named(BANNER_NAME_LS_SURVEY)
4445
private readonly surveyBanner: IPythonExtensionBanner,
4546
@inject(ILanguageServerFolderService) private readonly folderService: ILanguageServerFolderService,
46-
@inject(IExperimentsManager) private readonly experimentsManager: IExperimentsManager
47+
@inject(IExperimentsManager) private readonly experimentsManager: IExperimentsManager,
48+
@inject(IConfigurationService) private readonly configService: IConfigurationService
4749
) {}
4850
public dispose() {
4951
if (this.languageProxy) {
@@ -107,6 +109,7 @@ export class DotNetLanguageServerManager implements ILanguageServerManager {
107109
options.middleware = this.middleware = new LanguageClientMiddleware(
108110
this.surveyBanner,
109111
this.experimentsManager,
112+
this.configService,
110113
LanguageServerType.Microsoft,
111114
versionPair?.version.format()
112115
);

src/client/activation/node/manager.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { inject, injectable, named } from 'inversify';
77
import { traceDecorators } from '../../common/logger';
88
import {
99
BANNER_NAME_LS_SURVEY,
10+
IConfigurationService,
1011
IDisposable,
1112
IExperimentsManager,
1213
IPythonExtensionBanner,
@@ -41,7 +42,8 @@ export class NodeLanguageServerManager implements ILanguageServerManager {
4142
@named(BANNER_NAME_LS_SURVEY)
4243
private readonly surveyBanner: IPythonExtensionBanner,
4344
@inject(ILanguageServerFolderService) private readonly folderService: ILanguageServerFolderService,
44-
@inject(IExperimentsManager) private readonly experimentsManager: IExperimentsManager
45+
@inject(IExperimentsManager) private readonly experimentsManager: IExperimentsManager,
46+
@inject(IConfigurationService) private readonly configService: IConfigurationService
4547
) {}
4648

4749
public dispose() {
@@ -103,6 +105,7 @@ export class NodeLanguageServerManager implements ILanguageServerManager {
103105
options.middleware = this.middleware = new LanguageClientMiddleware(
104106
this.surveyBanner,
105107
this.experimentsManager,
108+
this.configService,
106109
LanguageServerType.Node,
107110
versionPair?.version.format()
108111
);

src/test/activation/languageServer/manager.unit.test.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,9 @@ import {
1616
ILanguageServerFolderService,
1717
ILanguageServerProxy
1818
} from '../../../client/activation/types';
19+
import { ConfigurationService } from '../../../client/common/configuration/service';
1920
import { ExperimentsManager } from '../../../client/common/experiments';
20-
import { IExperimentsManager, IPythonExtensionBanner } from '../../../client/common/types';
21+
import { IConfigurationService, IExperimentsManager, IPythonExtensionBanner } from '../../../client/common/types';
2122
import { ServiceContainer } from '../../../client/ioc/container';
2223
import { IServiceContainer } from '../../../client/ioc/types';
2324
import { ProposeLanguageServerBanner } from '../../../client/languageServices/proposeLanguageServerBanner';
@@ -37,6 +38,7 @@ suite('Language Server - Manager', () => {
3738
let surveyBanner: IPythonExtensionBanner;
3839
let folderService: ILanguageServerFolderService;
3940
let experimentsManager: IExperimentsManager;
41+
let configService: IConfigurationService;
4042
const languageClientOptions = ({ x: 1 } as any) as LanguageClientOptions;
4143
setup(() => {
4244
serviceContainer = mock(ServiceContainer);
@@ -46,13 +48,15 @@ suite('Language Server - Manager', () => {
4648
surveyBanner = mock(ProposeLanguageServerBanner);
4749
folderService = mock(DotNetLanguageServerFolderService);
4850
experimentsManager = mock(ExperimentsManager);
51+
configService = mock(ConfigurationService);
4952
manager = new DotNetLanguageServerManager(
5053
instance(serviceContainer),
5154
instance(analysisOptions),
5255
instance(lsExtension),
5356
instance(surveyBanner),
5457
instance(folderService),
55-
instance(experimentsManager)
58+
instance(experimentsManager),
59+
instance(configService)
5660
);
5761
});
5862

0 commit comments

Comments
 (0)