Start rust-analyzer server for arbitrary rust files

This commit is contained in:
Kirill Bulatov 2020-11-16 00:19:04 +02:00
parent 1605488710
commit d9a5490646
3 changed files with 46 additions and 39 deletions

View file

@ -23,7 +23,7 @@ function renderHoverActions(actions: ra.CommandLinkGroup[]): vscode.MarkdownStri
return result;
}
export function createClient(serverPath: string, cwd: string, extraEnv: Env): lc.LanguageClient {
export function createClient(serverPath: string, cwd: string | undefined, extraEnv: Env): lc.LanguageClient {
// '.' Is the fallback if no folder is open
// TODO?: Workspace folders support Uri's (eg: file://test.txt).
// It might be a good idea to test if the uri points to a file.

View file

@ -22,7 +22,7 @@ export class Ctx {
config: Config,
extCtx: vscode.ExtensionContext,
serverPath: string,
cwd: string,
cwd?: string,
): Promise<Ctx> {
const client = createClient(serverPath, cwd, config.serverExtraEnv);

View file

@ -7,7 +7,7 @@ import * as commands from './commands';
import { activateInlayHints } from './inlay_hints';
import { Ctx } from './ctx';
import { Config } from './config';
import { log, assert, isValidExecutable } from './util';
import { log, assert, isValidExecutable, isRustDocument } from './util';
import { PersistentState } from './persistent_state';
import { fetchRelease, download } from './net';
import { activateTaskProvider } from './tasks';
@ -28,26 +28,6 @@ export async function activate(context: vscode.ExtensionContext) {
}
async function tryActivate(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);
const state = new PersistentState(context.globalState);
const serverPath = await bootstrap(config, state).catch(err => {
@ -67,14 +47,52 @@ async function tryActivate(context: vscode.ExtensionContext) {
const workspaceFolder = vscode.workspace.workspaceFolders?.[0];
if (workspaceFolder === undefined) {
throw new Error("no folder is opened");
let rustDocuments = vscode.workspace.textDocuments.filter(document => isRustDocument(document));
if (rustDocuments.length > 0) {
ctx = await Ctx.create(config, context, serverPath);
} else {
throw new Error("no rust files are opened");
}
} else {
// 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, workspaceFolder.uri.fsPath);
ctx.pushCleanup(activateTaskProvider(workspaceFolder, ctx.config));
}
await initCommonContext(context, ctx);
// Note: we try to start the server before we activate type hints so that it
// registers its `onDidChangeDocument` handler before us.
activateInlayHints(ctx);
warnAboutExtensionConflicts();
vscode.workspace.onDidChangeConfiguration(
_ => ctx?.client?.sendNotification('workspace/didChangeConfiguration', { settings: "" }),
null,
ctx.subscriptions,
);
}
async function initCommonContext(context: vscode.ExtensionContext, ctx: Ctx) {
// Register a "dumb" onEnter command for the case where server fails to
// start.
//
// This a horribly, horribly wrong way to deal with this problem.
ctx = await Ctx.create(config, context, serverPath, workspaceFolder.uri.fsPath);
// 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);
await setContextValue(RUST_PROJECT_CONTEXT_NAME, true);
@ -134,17 +152,6 @@ async function tryActivate(context: vscode.ExtensionContext) {
ctx.registerCommand('resolveCodeAction', commands.resolveCodeAction);
ctx.registerCommand('applyActionGroup', commands.applyActionGroup);
ctx.registerCommand('gotoLocation', commands.gotoLocation);
ctx.pushCleanup(activateTaskProvider(workspaceFolder, ctx.config));
activateInlayHints(ctx);
warnAboutExtensionConflicts();
vscode.workspace.onDidChangeConfiguration(
_ => ctx?.client?.sendNotification('workspace/didChangeConfiguration', { settings: "" }),
null,
ctx.subscriptions,
);
}
export async function deactivate() {