Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use pylance client if pylance client is available/enabled. #19912

Closed
wants to merge 12 commits into from
43 changes: 40 additions & 3 deletions src/client/activation/node/languageServerProxy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,14 @@ namespace GetExperimentValue {
}
}

interface PylanceApi {
client?: {
isEnabled(): boolean;
start(): Promise<void>;
stop(): Promise<void>;
};
}

export class NodeLanguageServerProxy implements ILanguageServerProxy {
public languageClient: LanguageClient | undefined;

Expand All @@ -56,14 +64,18 @@ export class NodeLanguageServerProxy implements ILanguageServerProxy {

private lsVersion: string | undefined;

private pylanceApi: PylanceApi | undefined;

constructor(
private readonly factory: ILanguageClientFactory,
private readonly experimentService: IExperimentService,
private readonly interpreterPathService: IInterpreterPathService,
private readonly environmentService: IEnvironmentVariablesProvider,
private readonly workspace: IWorkspaceService,
private readonly extensions: IExtensions,
) {}
) {
// Empty
}

private static versionTelemetryProps(instance: NodeLanguageServerProxy) {
return {
Expand All @@ -89,9 +101,16 @@ export class NodeLanguageServerProxy implements ILanguageServerProxy {
interpreter: PythonEnvironment | undefined,
options: LanguageClientOptions,
): Promise<void> {
const extension = this.extensions.getExtension(PYLANCE_EXTENSION_ID);
const extension = await this.getPylanceExtension();
this.lsVersion = extension?.packageJSON.version || '0';

const api = extension?.exports as PylanceApi | undefined;
if (api && api.client && api.client.isEnabled()) {
this.pylanceApi = api;
await api.client.start();
return;
}

this.cancellationStrategy = new FileBasedCancellationStrategy();
options.connectionOptions = { cancellationStrategy: this.cancellationStrategy };

Expand All @@ -105,12 +124,17 @@ export class NodeLanguageServerProxy implements ILanguageServerProxy {
);

await client.start();

this.languageClient = client;
}

@traceDecoratorVerbose('Disposing language server')
public async stop(): Promise<void> {
if (this.pylanceApi) {
const api = this.pylanceApi;
this.pylanceApi = undefined;
await api.client!.stop();
}

while (this.disposables.length > 0) {
const d = this.disposables.shift()!;
d.dispose();
Expand Down Expand Up @@ -203,4 +227,17 @@ export class NodeLanguageServerProxy implements ILanguageServerProxy {
})),
);
}

private async getPylanceExtension() {
const extension = this.extensions.getExtension(PYLANCE_EXTENSION_ID);
if (!extension) {
return undefined;
}

if (!extension.isActive) {
await extension.activate();
}

return extension;
}
}
35 changes: 33 additions & 2 deletions src/client/browser/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,16 @@ interface BrowserConfig {
distUrl: string; // URL to Pylance's dist folder.
}

interface PylanceApi {
client?: {
isEnabled(): boolean;
start(): Promise<void>;
stop(): Promise<void>;
};
}

let languageClient: LanguageClient | undefined;
let pylanceApi: PylanceApi | undefined;

export async function activate(context: vscode.ExtensionContext): Promise<void> {
const pylanceExtension = vscode.extensions.getExtension(PYLANCE_EXTENSION_ID);
Expand All @@ -35,6 +44,12 @@ export async function activate(context: vscode.ExtensionContext): Promise<void>
}

export async function deactivate(): Promise<void> {
if (pylanceApi) {
const api = pylanceApi;
pylanceApi = undefined;
await api.client!.stop();
}

const client = languageClient;
languageClient = undefined;

Expand All @@ -46,6 +61,16 @@ async function runPylance(
context: vscode.ExtensionContext,
pylanceExtension: vscode.Extension<unknown>,
): Promise<void> {
context.subscriptions.push(createStatusItem());

pylanceExtension = await getActivatedExtension(pylanceExtension);
const api = pylanceExtension.exports as PylanceApi;
if (api.client && api.client.isEnabled()) {
pylanceApi = api;
await api.client.start();
return;
}

const { extensionUri, packageJSON } = pylanceExtension;
const distUrl = vscode.Uri.joinPath(extensionUri, 'dist');

Expand Down Expand Up @@ -112,8 +137,6 @@ async function runPylance(
);

await client.start();

context.subscriptions.push(createStatusItem());
} catch (e) {
console.log(e);
}
Expand Down Expand Up @@ -204,3 +227,11 @@ function sendTelemetryEventBrowser(
reporter.sendTelemetryEvent(eventNameSent, customProperties, measures);
}
}

async function getActivatedExtension<T>(extension: vscode.Extension<T>): Promise<vscode.Extension<T>> {
if (!extension.isActive) {
await extension.activate();
}

return extension;
}
6 changes: 4 additions & 2 deletions src/client/languageServer/watcher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -265,11 +265,11 @@ export class LanguageServerWatcher implements IExtensionActivationService, ILang
return lsManager;
}

private async refreshLanguageServer(resource?: Resource): Promise<void> {
private async refreshLanguageServer(resource?: Resource, forced?: boolean): Promise<void> {
const lsResource = this.getWorkspaceUri(resource);
const languageServerType = this.configurationService.getSettings(lsResource).languageServer;

if (languageServerType !== this.languageServerType) {
if (languageServerType !== this.languageServerType || forced) {
await this.stopLanguageServer(resource);
await this.startLanguageServer(languageServerType, lsResource);
}
Expand All @@ -286,6 +286,8 @@ export class LanguageServerWatcher implements IExtensionActivationService, ILang
workspacesUris.forEach(async (resource) => {
if (event.affectsConfiguration(`python.languageServer`, resource)) {
await this.refreshLanguageServer(resource);
} else if (event.affectsConfiguration(`python.analysis.pylanceLspClientEnabled`, resource)) {
await this.refreshLanguageServer(resource, /* forced */ true);
}
});
}
Expand Down