Skip to content

Commit

Permalink
Update utilities.ts
Browse files Browse the repository at this point in the history
  • Loading branch information
charliermarsh committed Jun 17, 2023
1 parent 9a1e8ed commit d595265
Show file tree
Hide file tree
Showing 9 changed files with 285 additions and 232 deletions.
3 changes: 1 addition & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,14 +41,13 @@ per workspace in Visual Studio Code.
| Settings | Default | Description |
| ---------------- | ----------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| args | `[]` | Additional command-line arguments to pass to `ruff`, e.g., `"args": ["--config=/path/to/pyproject.toml"]`. Supports a subset of Ruff's command-line arguments, ignoring those that are required to operate the LSP, like `--force-exclude` and `--verbose`. |
| logLevel | `error` | Sets the tracing level for the extension: `error`, `warn`, `info`, or `debug`. |
| path | `[]` | Path to a custom `ruff` executable, e.g., `["/path/to/ruff"]`. |
| interpreter | `[]` | Path to a Python interpreter to use to run the linter server. |
| importStrategy | `fromEnvironment` | Strategy for loading the `ruff` executable. `fromEnvironment` picks up Ruff from the environment, falling back to the bundled version if needed. `useBundled` uses the version bundled with the extension. |
| run | `onType` | Run Ruff on every keystroke (`onType`) or on save (`onSave`). |
| showNotification | `off` | Setting to control when a notification is shown: `off`, `onError`, `onWarning`, `always`. |
| enable | `true` | Whether to enable the Ruff extension. Modifying this setting requires restarting VS Code to take effect. |
| organizeImports | `true` | Whether to register Ruff as capable of handling `source.organizeImports` actions. |
| showNotification | `off` | Setting to control when a notification is shown: `off`, `onError`, `onWarning`, `always`. |
| fixAll | `true` | Whether to register Ruff as capable of handling `source.fixAll` actions. |

### Example configurations
Expand Down
26 changes: 13 additions & 13 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

51 changes: 19 additions & 32 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -55,19 +55,6 @@
"contributes": {
"configuration": {
"properties": {
"ruff.logLevel": {
"default": "error",
"description": "Sets the tracing level for the extension: `error`, `warn`, `info`, or `debug`.",
"enum": [
"debug",
"error",
"info",
"off",
"warn"
],
"scope": "window",
"type": "string"
},
"ruff.args": {
"default": [],
"description": "Additional command-line arguments to pass to `ruff`, e.g., `\"args\": [\"--config=/path/to/pyproject.toml\"]`. Supports a subset of Ruff's command-line arguments, ignoring those that are required to operate the LSP, like `--force-exclude` and `--verbose`.",
Expand Down Expand Up @@ -123,24 +110,6 @@
},
"type": "array"
},
"ruff.showNotifications": {
"default": "off",
"description": "Controls when notifications are shown by this extension.",
"enum": [
"off",
"onError",
"onWarning",
"always"
],
"enumDescriptions": [
"All notifications are turned off, any errors or warning are still available in the logs.",
"Notifications are shown only in the case of an error.",
"Notifications are shown for errors and warnings.",
"Notifications are show for anything that the server chooses to show."
],
"scope": "machine",
"type": "string"
},
"ruff.enable": {
"default": true,
"description": "Whether to enable the Ruff extension.",
Expand Down Expand Up @@ -168,6 +137,24 @@
],
"default": "off",
"markdownDescription": "Traces the communication between VSCode and the ruff-lsp."
},
"ruff.showNotifications": {
"default": "off",
"description": "Controls when notifications are shown by this extension.",
"enum": [
"off",
"onError",
"onWarning",
"always"
],
"enumDescriptions": [
"All notifications are turned off, any errors or warning are still available in the logs.",
"Notifications are shown only in the case of an error.",
"Notifications are shown for errors and warnings.",
"Notifications are show for anything that the server chooses to show."
],
"scope": "machine",
"type": "string"
}
}
},
Expand All @@ -190,7 +177,7 @@
]
},
"dependencies": {
"fs-extra": "^11.1.0",
"fs-extra": "^11.1.1",
"ovsx": "^0.7.1",
"vscode-languageclient": "^8.1.0"
},
Expand Down
3 changes: 0 additions & 3 deletions src/common/log/logging.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

import * as util from "util";
import { Disposable, LogOutputChannel } from "vscode";

Expand Down
4 changes: 0 additions & 4 deletions src/common/python.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,3 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

/* eslint-disable @typescript-eslint/naming-convention */
import {
commands,
Disposable,
Expand Down
142 changes: 52 additions & 90 deletions src/common/server.ts
Original file line number Diff line number Diff line change
@@ -1,91 +1,64 @@
import { Disposable, OutputChannel } from "vscode";
import * as fsapi from "fs-extra";
import { Disposable, env, LogOutputChannel } from "vscode";
import { State } from "vscode-languageclient";
import {
Executable,
LanguageClient,
LanguageClientOptions,
RevealOutputChannelOn,
ServerOptions,
} from "vscode-languageclient/node";
import { DEBUG_SERVER_SCRIPT_PATH, SERVER_SCRIPT_PATH } from "./constants";
import { traceError, traceInfo, traceLog, traceVerbose } from "./log/logging";
import { traceError, traceInfo, traceVerbose } from "./log/logging";
import { getDebuggerPath } from "./python";
import {
getExtensionSettings,
getGlobalSettings,
getWorkspaceSettings,
ISettings,
} from "./settings";
import { getProjectRoot, traceLevelToLSTrace } from "./utilities";
import { getLSClientTraceLevel, getProjectRoot } from "./utilities";
import { isVirtualWorkspace } from "./vscodeapi";

export type IInitOptions = { settings: ISettings[]; globalSettings: Omit<ISettings, "workspace"> };
export type IInitOptions = { settings: ISettings[]; globalSettings: ISettings };

async function getDebugServerOptions(
interpreter: string[],
cwd?: string,
env?: {
[x: string]: string | undefined;
},
): Promise<Executable> {
// Set debugger path needed for debugging Python code.
if (env) {
if (env.DEBUGPY_ENABLED !== "False") {
env.DEBUGPY_PATH = await getDebuggerPath();
}
}

const command = interpreter[0];
const args = interpreter.slice(1).concat([DEBUG_SERVER_SCRIPT_PATH]);
traceLog(`Server Command [DEBUG]: ${[command, ...args].join(" ")}`);

return {
command,
args,
options: { cwd, env },
};
}

async function getRunServerOptions(
interpreter: string[],
cwd?: string,
env?: {
[x: string]: string | undefined;
},
): Promise<Executable> {
const command = interpreter[0];
const args = interpreter.slice(1).concat([SERVER_SCRIPT_PATH]);
traceLog(`Server Command [RUN]: ${[command, ...args].join(" ")}`);

return Promise.resolve({
command,
args,
options: { cwd, env },
});
}

export async function createServer(
interpreter: string[],
async function createServer(
settings: ISettings,
serverId: string,
serverName: string,
outputChannel: OutputChannel,
outputChannel: LogOutputChannel,
initializationOptions: IInitOptions,
settings: Omit<ISettings, "workspace">,
): Promise<LanguageClient> {
const cwd = getProjectRoot()?.uri.fsPath;
const command = settings.interpreter[0];
const cwd = settings.cwd;

// Set debugger path needed for debugging python code.
const newEnv = { ...process.env };
const debuggerPath = await getDebuggerPath();
const isDebugScript = await fsapi.pathExists(DEBUG_SERVER_SCRIPT_PATH);
if (newEnv.USE_DEBUGPY && debuggerPath) {
newEnv.DEBUGPY_PATH = debuggerPath;
} else {
newEnv.USE_DEBUGPY = "False";
}

// Set notification type.
// Set notification type
newEnv.LS_SHOW_NOTIFICATION = settings.showNotifications;

const args =
newEnv.USE_DEBUGPY === "False" || !isDebugScript
? settings.interpreter.slice(1).concat([SERVER_SCRIPT_PATH])
: settings.interpreter.slice(1).concat([DEBUG_SERVER_SCRIPT_PATH]);
traceInfo(`Server run command: ${[command, ...args].join(" ")}`);

const serverOptions: ServerOptions = {
run: await getRunServerOptions(interpreter, cwd, { ...newEnv }),
debug: await getDebugServerOptions(interpreter, cwd, { ...newEnv }),
command,
args,
options: { cwd, env: newEnv },
};

// Options to control the language client.
// Options to control the language client
const clientOptions: LanguageClientOptions = {
// Register the server for python documents.
// Register the server for python documents
documentSelector: isVirtualWorkspace()
? [{ language: "python" }]
: [
Expand All @@ -104,47 +77,28 @@ export async function createServer(
}

let _disposables: Disposable[] = [];

export async function restartServer(
serverId: string,
serverName: string,
outputChannel: OutputChannel,
client?: LanguageClient,
outputChannel: LogOutputChannel,
lsClient?: LanguageClient,
): Promise<LanguageClient | undefined> {
if (client) {
if (lsClient) {
traceInfo(`Server: Stop requested`);
await client.stop();
await lsClient.stop();
_disposables.forEach((d) => d.dispose());
_disposables = [];
}
const projectRoot = await getProjectRoot();
const workspaceSetting = await getWorkspaceSettings(serverId, projectRoot, true);

const workspaceFolder = getProjectRoot();
const resourceSettings = await getWorkspaceSettings(serverId, workspaceFolder?.uri);
if (resourceSettings.interpreter.length === 0) {
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`,
);
return undefined;
}

const newClient = await createServer(
resourceSettings.interpreter,
serverId,
serverName,
outputChannel,
{
settings: await getExtensionSettings(serverId),
globalSettings: await getGlobalSettings(serverId),
},
resourceSettings,
);

newClient.trace = traceLevelToLSTrace(resourceSettings.logLevel);
const newLSClient = await createServer(workspaceSetting, serverId, serverName, outputChannel, {
settings: await getExtensionSettings(serverId, true),
globalSettings: await getGlobalSettings(serverId, false),
});
traceInfo(`Server: Start requested.`);
_disposables.push(
newClient.onDidChangeState((e) => {
newLSClient.onDidChangeState((e) => {
switch (e.newState) {
case State.Stopped:
traceVerbose(`Server State: Stopped`);
Expand All @@ -157,7 +111,15 @@ export async function restartServer(
break;
}
}),
newClient.start(),
);
return newClient;
try {
await newLSClient.start();
} catch (ex) {
traceError(`Server: Start failed: ${ex}`);
return undefined;
}

const level = getLSClientTraceLevel(outputChannel.logLevel, env.logLevel);
await newLSClient.setTrace(level);
return newLSClient;
}
Loading

0 comments on commit d595265

Please sign in to comment.