oxc/editors/vscode/client/extension.ts

195 lines
5.1 KiB
TypeScript

import {
ExtensionContext,
window,
commands,
workspace,
StatusBarItem,
StatusBarAlignment,
ConfigurationTarget,
ThemeColor,
} from "vscode";
import {
Executable,
LanguageClient,
LanguageClientOptions,
ServerOptions,
} from "vscode-languageclient/node";
import { join } from "node:path";
const languageClientId = "oxc-vscode";
const languageClientName = "oxc";
const outputChannelName = "oxc_language_server";
const traceOutputChannelName = "oxc_language_server.trace";
const enum OxcCommands {
RestartServer = "oxc.restartServer",
ApplyAllFixes = "oxc.applyAllFixes",
ShowOutputChannel = "oxc.showOutputChannel",
ShowTraceOutputChannel = "oxc.showTraceOutputChannel",
ToggleEnable = "oxc.toggleEnable",
}
let client: LanguageClient;
let myStatusBarItem: StatusBarItem;
export async function activate(context: ExtensionContext) {
const restartCommand = commands.registerCommand(
OxcCommands.RestartServer,
async () => {
if (!client) {
window.showErrorMessage("oxc client not found");
return;
}
try {
if (client.isRunning()) {
await client.restart();
window.showInformationMessage("oxc server restarted.");
} else {
await client.start();
}
} catch (err) {
client.error("Restarting client failed", err, "force");
}
},
);
const showOutputCommand = commands.registerCommand(
OxcCommands.ShowOutputChannel,
() => {
client?.outputChannel?.show();
},
);
const showTraceOutputCommand = commands.registerCommand(
OxcCommands.ShowTraceOutputChannel,
() => {
client?.traceOutputChannel?.show();
},
);
const toggleEnable = commands.registerCommand(
OxcCommands.ToggleEnable,
() => {
let enabled = workspace
.getConfiguration("oxc_language_server")
.get("enable");
let nextState = !enabled;
workspace
.getConfiguration("oxc_language_server")
.update("enable", nextState, ConfigurationTarget.Global);
},
);
context.subscriptions.push(
restartCommand,
showOutputCommand,
showTraceOutputCommand,
toggleEnable,
);
const outputChannel = window.createOutputChannel(outputChannelName);
const traceOutputChannel = window.createOutputChannel(traceOutputChannelName);
const ext = process.platform === "win32" ? ".exe" : "";
// NOTE: The `./target/release` path is aligned with the path defined in .github/workflows/release_vscode.yml
const command =
process.env.SERVER_PATH_DEV ??
join(context.extensionPath, `./target/release/oxc_language_server${ext}`);
const run: Executable = {
command: command!,
options: {
env: {
...process.env,
RUST_LOG: process.env.RUST_LOG || "info",
},
},
};
const serverOptions: ServerOptions = {
run,
debug: run,
};
// If the extension is launched in debug mode then the debug server options are used
// Otherwise the run options are used
// Options to control the language client
let clientConfig: any = JSON.parse(
JSON.stringify(workspace.getConfiguration("oxc_language_server")),
);
let clientOptions: LanguageClientOptions = {
// Register the server for plain text documents
documentSelector: [
"typescript",
"javascript",
"typescriptreact",
"javascriptreact",
"vue",
"svelte",
].map((lang) => ({
language: lang,
scheme: "file",
})),
synchronize: {
// Notify the server about file changes to '.clientrc files contained in the workspace
fileEvents: workspace.createFileSystemWatcher("**/.clientrc"),
},
initializationOptions: {
settings: clientConfig,
},
outputChannel,
traceOutputChannel,
};
// Create the language client and start the client.
client = new LanguageClient(
languageClientId,
languageClientName,
serverOptions,
clientOptions,
);
workspace.onDidChangeConfiguration((e) => {
let isAffected = e.affectsConfiguration("oxc_language_server");
if (!isAffected) {
return;
}
let settings: any = JSON.parse(
JSON.stringify(workspace.getConfiguration("oxc_language_server")),
);
updateStatsBar(settings.enable);
client.sendNotification("workspace/didChangeConfiguration", { settings });
});
function updateStatsBar(enable: boolean) {
if (!myStatusBarItem) {
myStatusBarItem = window.createStatusBarItem(
StatusBarAlignment.Right,
100,
);
myStatusBarItem.command = OxcCommands.ToggleEnable;
context.subscriptions.push(myStatusBarItem);
myStatusBarItem.show();
}
let bgColor = new ThemeColor(
enable
? "statusBarItem.activeBackground"
: "statusBarItem.errorBackground",
);
myStatusBarItem.text = `oxc: ${
enable ? "$(check-all)" : "$(circle-slash)"
}`;
myStatusBarItem.backgroundColor = bgColor;
}
updateStatsBar(clientConfig.enable);
client.start();
}
export function deactivate(): Thenable<void> | undefined {
if (!client) {
return undefined;
}
return client.stop();
}