mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-12-28 05:53:45 +00:00
200c275c2e
3534: Feature: vscode impl nightlies download and installation r=Veetaha a=Veetaha I need to test things more, but the core shape of the code is quite well-formed. The main problem is that we save the release date only for nightlies and there are no means to get the release date of the stable extension (i.e. for this we would need to consult the github releases via a network request, or we would need to somehow save this info into package.json or any other file accessible from the extension code during the deployment step, but this will be very hard I guess). So there is an invariant that the users can install nightly only from our extension and they can't do it manually, because when installing the nightly `.vsix` we actually save its release date to `globalState` Closes: #3402 TODO: - [x] More manual tests and documentation cc @matklad @lnicola Co-authored-by: Veetaha <gerzoh1@gmail.com> Co-authored-by: Veetaha <veetaha2@gmail.com>
109 lines
4.1 KiB
TypeScript
109 lines
4.1 KiB
TypeScript
import * as vscode from 'vscode';
|
|
|
|
import * as commands from './commands';
|
|
import { activateInlayHints } from './inlay_hints';
|
|
import { activateStatusDisplay } from './status_display';
|
|
import { Ctx } from './ctx';
|
|
import { activateHighlighting } from './highlighting';
|
|
import { ensureServerBinary } from './installation/server';
|
|
import { Config } from './config';
|
|
import { log } from './util';
|
|
import { ensureProperExtensionVersion } from './installation/extension';
|
|
|
|
let ctx: Ctx | undefined;
|
|
|
|
export async function activate(context: vscode.ExtensionContext) {
|
|
// Register a "dumb" onEnter command for the case where server fails to
|
|
// start.
|
|
//
|
|
// FIXME: refactor command registration code such that commands are
|
|
// **always** registered, even if the server does not start. Use API like
|
|
// this perhaps?
|
|
//
|
|
// ```TypeScript
|
|
// registerCommand(
|
|
// factory: (Ctx) => ((Ctx) => any),
|
|
// fallback: () => any = () => vscode.window.showErrorMessage(
|
|
// "rust-analyzer is not available"
|
|
// ),
|
|
// )
|
|
const defaultOnEnter = vscode.commands.registerCommand(
|
|
'rust-analyzer.onEnter',
|
|
() => vscode.commands.executeCommand('default:type', { text: '\n' }),
|
|
);
|
|
context.subscriptions.push(defaultOnEnter);
|
|
|
|
const config = new Config(context);
|
|
|
|
vscode.workspace.onDidChangeConfiguration(() => ensureProperExtensionVersion(config).catch(log.error));
|
|
|
|
// Don't await the user response here, otherwise we will block the lsp server bootstrap
|
|
void ensureProperExtensionVersion(config).catch(log.error);
|
|
|
|
const serverPath = await ensureServerBinary(config);
|
|
|
|
if (serverPath == null) {
|
|
throw new Error(
|
|
"Rust Analyzer Language Server is not available. " +
|
|
"Please, ensure its [proper installation](https://rust-analyzer.github.io/manual.html#installation)."
|
|
);
|
|
}
|
|
|
|
// Note: we try to start the server before we activate type hints so that it
|
|
// registers its `onDidChangeDocument` handler before us.
|
|
//
|
|
// This a horribly, horribly wrong way to deal with this problem.
|
|
ctx = await Ctx.create(config, context, serverPath);
|
|
|
|
// Commands which invokes manually via command palette, shortcut, etc.
|
|
ctx.registerCommand('reload', (ctx) => {
|
|
return async () => {
|
|
vscode.window.showInformationMessage('Reloading rust-analyzer...');
|
|
// @DanTup maneuver
|
|
// https://github.com/microsoft/vscode/issues/45774#issuecomment-373423895
|
|
await deactivate();
|
|
for (const sub of ctx.subscriptions) {
|
|
try {
|
|
sub.dispose();
|
|
} catch (e) {
|
|
log.error(e);
|
|
}
|
|
}
|
|
await activate(context);
|
|
};
|
|
});
|
|
|
|
ctx.registerCommand('analyzerStatus', commands.analyzerStatus);
|
|
ctx.registerCommand('collectGarbage', commands.collectGarbage);
|
|
ctx.registerCommand('matchingBrace', commands.matchingBrace);
|
|
ctx.registerCommand('joinLines', commands.joinLines);
|
|
ctx.registerCommand('parentModule', commands.parentModule);
|
|
ctx.registerCommand('syntaxTree', commands.syntaxTree);
|
|
ctx.registerCommand('expandMacro', commands.expandMacro);
|
|
ctx.registerCommand('run', commands.run);
|
|
|
|
defaultOnEnter.dispose();
|
|
ctx.registerCommand('onEnter', commands.onEnter);
|
|
|
|
ctx.registerCommand('ssr', commands.ssr);
|
|
ctx.registerCommand('serverVersion', commands.serverVersion);
|
|
|
|
// Internal commands which are invoked by the server.
|
|
ctx.registerCommand('runSingle', commands.runSingle);
|
|
ctx.registerCommand('debugSingle', commands.debugSingle);
|
|
ctx.registerCommand('showReferences', commands.showReferences);
|
|
ctx.registerCommand('applySourceChange', commands.applySourceChange);
|
|
ctx.registerCommand('selectAndApplySourceChange', commands.selectAndApplySourceChange);
|
|
|
|
activateStatusDisplay(ctx);
|
|
|
|
if (!ctx.config.highlightingSemanticTokens) {
|
|
activateHighlighting(ctx);
|
|
}
|
|
activateInlayHints(ctx);
|
|
}
|
|
|
|
export async function deactivate() {
|
|
await ctx?.client?.stop();
|
|
ctx = undefined;
|
|
}
|