Skip to content
Merged
1 change: 1 addition & 0 deletions src/common/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,4 @@ export const EXTENSION_ROOT_DIR =
export const BUNDLED_PYTHON_SCRIPTS_DIR = path.join(EXTENSION_ROOT_DIR, 'bundled');
export const SERVER_SCRIPT_PATH = path.join(BUNDLED_PYTHON_SCRIPTS_DIR, 'tool', `lsp_server.py`);
export const DEBUG_SERVER_SCRIPT_PATH = path.join(BUNDLED_PYTHON_SCRIPTS_DIR, 'tool', `_debug_server.py`);
export const LS_SERVER_RESTART_DELAY = 1000; // Delay before restarting the LS in case of multiple configuration change events.
10 changes: 7 additions & 3 deletions src/common/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,10 +86,14 @@ export async function restartServer(
): Promise<LanguageClient | undefined> {
if (lsClient) {
traceInfo(`Server: Stop requested`);
await lsClient.stop();
_disposables.forEach((d) => d.dispose());
_disposables = [];
try {
await lsClient.stop();
} catch (ex) {
traceError(`Server: Stop failed: ${ex}`);
}
}
_disposables.forEach((d) => d.dispose());
_disposables = [];
const projectRoot = await getProjectRoot();
const workspaceSetting = await getWorkspaceSettings(serverId, projectRoot, true);

Expand Down
6 changes: 6 additions & 0 deletions src/common/settings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,13 @@ export function checkIfConfigurationChanged(e: ConfigurationChangeEvent, namespa
`${namespace}.interpreter`,
`${namespace}.importStrategy`,
`${namespace}.showNotifications`,
`${namespace}.serverEnabled`,
];
const changed = settings.map((s) => e.affectsConfiguration(s));
return changed.includes(true);
}

export function getServerEnabled(namespace: string): boolean {
const config = getConfiguration(namespace);
return config.get<boolean>('serverEnabled', true);
}
69 changes: 50 additions & 19 deletions src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,15 @@ import {
resolveInterpreter,
} from './common/python';
import { restartServer } from './common/server';
import { checkIfConfigurationChanged, getInterpreterFromSetting } from './common/settings';
import { checkIfConfigurationChanged, getInterpreterFromSetting, getServerEnabled } from './common/settings';
import { loadServerDefaults } from './common/setup';
import { LS_SERVER_RESTART_DELAY } from './common/constants';
import { getLSClientTraceLevel } from './common/utilities';
import { createOutputChannel, onDidChangeConfiguration, registerCommand } from './common/vscodeapi';

let lsClient: LanguageClient | undefined;
let isRestarting = false;
let restartTimer: NodeJS.Timeout | undefined;
export async function activate(context: vscode.ExtensionContext): Promise<void> {
// This is required to get server name and module. This should be
// the first thing that we do in this extension.
Expand Down Expand Up @@ -49,28 +52,52 @@ export async function activate(context: vscode.ExtensionContext): Promise<void>
traceVerbose(`Full Server Info: ${JSON.stringify(serverInfo)}`);

const runServer = async () => {
const interpreter = getInterpreterFromSetting(serverId);
if (interpreter && interpreter.length > 0) {
if (checkVersion(await resolveInterpreter(interpreter))) {
traceVerbose(`Using interpreter from ${serverInfo.module}.interpreter: ${interpreter.join(' ')}`);
lsClient = await restartServer(serverId, serverName, outputChannel, lsClient);
if (isRestarting) {
if (restartTimer) {
clearTimeout(restartTimer);
}
restartTimer = setTimeout(runServer, LS_SERVER_RESTART_DELAY);
return;
}
isRestarting = true;
try {
if (!getServerEnabled(serverId)) {
if (lsClient) {
try {
await lsClient.stop();
} catch (ex) {
traceError(`Server: Stop failed: ${ex}`);
}
lsClient = undefined;
}
return;
}

const interpreterDetails = await getInterpreterDetails();
if (interpreterDetails.path) {
traceVerbose(`Using interpreter from Python extension: ${interpreterDetails.path.join(' ')}`);
lsClient = await restartServer(serverId, serverName, outputChannel, lsClient);
return;
}
const interpreter = getInterpreterFromSetting(serverId);
if (interpreter && interpreter.length > 0) {
if (checkVersion(await resolveInterpreter(interpreter))) {
traceVerbose(`Using interpreter from ${serverInfo.module}.interpreter: ${interpreter.join(' ')}`);
lsClient = await restartServer(serverId, serverName, outputChannel, lsClient);
}
return;
}

traceError(
'Python interpreter missing:\r\n' +
'[Option 1] Select python interpreter using the ms-python.python.\r\n' +
`[Option 2] Set an interpreter using "${serverId}.interpreter" setting.\r\n` +
'Please use Python 3.8 or greater.',
);
const interpreterDetails = await getInterpreterDetails();
if (interpreterDetails.path) {
traceVerbose(`Using interpreter from Python extension: ${interpreterDetails.path.join(' ')}`);
lsClient = await restartServer(serverId, serverName, outputChannel, lsClient);
return;
}

traceError(
'Python interpreter missing:\r\n' +
'[Option 1] Select python interpreter using the ms-python.python.\r\n' +
`[Option 2] Set an interpreter using "${serverId}.interpreter" setting.\r\n` +
'Please use Python 3.8 or greater.',
);
} finally {
isRestarting = false;
}
};

context.subscriptions.push(
Expand Down Expand Up @@ -101,6 +128,10 @@ export async function activate(context: vscode.ExtensionContext): Promise<void>

export async function deactivate(): Promise<void> {
if (lsClient) {
await lsClient.stop();
try {
await lsClient.stop();
} catch (ex) {
traceError(`Server: Stop failed: ${ex}`);
}
}
}