From d9a5490646f68efdb70f84713d3a418a2b2a0b00 Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Mon, 16 Nov 2020 00:19:04 +0200 Subject: Start rust-analyzer server for arbitrary rust files --- editors/code/src/client.ts | 2 +- editors/code/src/ctx.ts | 2 +- editors/code/src/main.ts | 81 +++++++++++++++++++++++++--------------------- 3 files changed, 46 insertions(+), 39 deletions(-) (limited to 'editors') diff --git a/editors/code/src/client.ts b/editors/code/src/client.ts index 116f41df6..131a2f19a 100644 --- a/editors/code/src/client.ts +++ b/editors/code/src/client.ts @@ -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. diff --git a/editors/code/src/ctx.ts b/editors/code/src/ctx.ts index bd023f803..9d8620823 100644 --- a/editors/code/src/ctx.ts +++ b/editors/code/src/ctx.ts @@ -22,7 +22,7 @@ export class Ctx { config: Config, extCtx: vscode.ExtensionContext, serverPath: string, - cwd: string, + cwd?: string, ): Promise { const client = createClient(serverPath, cwd, config.serverExtraEnv); diff --git a/editors/code/src/main.ts b/editors/code/src/main.ts index aaedc2431..f0f47a75b 100644 --- a/editors/code/src/main.ts +++ b/editors/code/src/main.ts @@ -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); + + activateInlayHints(ctx); + warnAboutExtensionConflicts(); + + vscode.workspace.onDidChangeConfiguration( + _ => ctx?.client?.sendNotification('workspace/didChangeConfiguration', { settings: "" }), + null, + ctx.subscriptions, + ); +} - // Note: we try to start the server before we activate type hints so that it - // registers its `onDidChangeDocument` handler before us. +async function initCommonContext(context: vscode.ExtensionContext, ctx: Ctx) { + // 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? // - // This a horribly, horribly wrong way to deal with this problem. - ctx = await Ctx.create(config, context, serverPath, workspaceFolder.uri.fsPath); + // ```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() { -- cgit v1.2.3 From b3383b06614e5f302a3afa2fc2c177303b5b6ca8 Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Sun, 23 May 2021 16:22:13 +0300 Subject: Send detached files info to server via init params --- editors/code/src/client.ts | 15 +++++++++++++-- editors/code/src/ctx.ts | 14 ++++++++++++-- editors/code/src/main.ts | 4 ++-- 3 files changed, 27 insertions(+), 6 deletions(-) (limited to 'editors') diff --git a/editors/code/src/client.ts b/editors/code/src/client.ts index 131a2f19a..cb8beb343 100644 --- a/editors/code/src/client.ts +++ b/editors/code/src/client.ts @@ -4,6 +4,7 @@ import * as ra from '../src/lsp_ext'; import * as Is from 'vscode-languageclient/lib/common/utils/is'; import { assert } from './util'; import { WorkspaceEdit } from 'vscode'; +import { Workspace } from './ctx'; export interface Env { [name: string]: string; @@ -23,7 +24,7 @@ function renderHoverActions(actions: ra.CommandLinkGroup[]): vscode.MarkdownStri return result; } -export function createClient(serverPath: string, cwd: string | undefined, extraEnv: Env): lc.LanguageClient { +export function createClient(serverPath: string, workspace: Workspace, 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. @@ -31,6 +32,11 @@ export function createClient(serverPath: string, cwd: string | undefined, extraE const newEnv = Object.assign({}, process.env); Object.assign(newEnv, extraEnv); + let cwd = undefined; + if (workspace.kind == "Workspace Folder") { + cwd = workspace.folder.fsPath; + }; + const run: lc.Executable = { command: serverPath, options: { cwd, env: newEnv }, @@ -43,9 +49,14 @@ export function createClient(serverPath: string, cwd: string | undefined, extraE 'Rust Analyzer Language Server Trace', ); + let initializationOptions = vscode.workspace.getConfiguration("rust-analyzer"); + if (workspace.kind == "Detached files") { + initializationOptions = { "detachedFiles": workspace.files.map(file => file.uri.fsPath), ...initializationOptions }; + } + const clientOptions: lc.LanguageClientOptions = { documentSelector: [{ scheme: 'file', language: 'rust' }], - initializationOptions: vscode.workspace.getConfiguration("rust-analyzer"), + initializationOptions, diagnosticCollectionName: "rustc", traceOutputChannel, middleware: { diff --git a/editors/code/src/ctx.ts b/editors/code/src/ctx.ts index 9d8620823..dbfb9c6a1 100644 --- a/editors/code/src/ctx.ts +++ b/editors/code/src/ctx.ts @@ -7,6 +7,16 @@ import { createClient } from './client'; import { isRustEditor, RustEditor } from './util'; import { ServerStatusParams } from './lsp_ext'; +export type Workspace = + { + kind: 'Workspace Folder', + folder: vscode.Uri, + } + | { + kind: 'Detached files', + files: vscode.TextDocument[], + }; + export class Ctx { private constructor( readonly config: Config, @@ -22,9 +32,9 @@ export class Ctx { config: Config, extCtx: vscode.ExtensionContext, serverPath: string, - cwd?: string, + workspace: Workspace, ): Promise { - const client = createClient(serverPath, cwd, config.serverExtraEnv); + const client = createClient(serverPath, workspace, config.serverExtraEnv); const statusBar = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Left); extCtx.subscriptions.push(statusBar); diff --git a/editors/code/src/main.ts b/editors/code/src/main.ts index f0f47a75b..1a4af548d 100644 --- a/editors/code/src/main.ts +++ b/editors/code/src/main.ts @@ -49,7 +49,7 @@ async function tryActivate(context: vscode.ExtensionContext) { if (workspaceFolder === undefined) { let rustDocuments = vscode.workspace.textDocuments.filter(document => isRustDocument(document)); if (rustDocuments.length > 0) { - ctx = await Ctx.create(config, context, serverPath); + ctx = await Ctx.create(config, context, serverPath, { kind: 'Detached files', files: rustDocuments }); } else { throw new Error("no rust files are opened"); } @@ -58,7 +58,7 @@ async function tryActivate(context: vscode.ExtensionContext) { // 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 = await Ctx.create(config, context, serverPath, { kind: "Workspace Folder", folder: workspaceFolder.uri }); ctx.pushCleanup(activateTaskProvider(workspaceFolder, ctx.config)); } await initCommonContext(context, ctx); -- cgit v1.2.3 From c1f6a5a0b0df92b6fb61aab92fe612d179fbab5d Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Sun, 23 May 2021 23:47:58 +0300 Subject: Fix ts lint errors --- editors/code/src/client.ts | 4 ++-- editors/code/src/ctx.ts | 8 ++++---- editors/code/src/main.ts | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) (limited to 'editors') diff --git a/editors/code/src/client.ts b/editors/code/src/client.ts index cb8beb343..69dbe2535 100644 --- a/editors/code/src/client.ts +++ b/editors/code/src/client.ts @@ -33,7 +33,7 @@ export function createClient(serverPath: string, workspace: Workspace, extraEnv: Object.assign(newEnv, extraEnv); let cwd = undefined; - if (workspace.kind == "Workspace Folder") { + if (workspace.kind === "Workspace Folder") { cwd = workspace.folder.fsPath; }; @@ -50,7 +50,7 @@ export function createClient(serverPath: string, workspace: Workspace, extraEnv: ); let initializationOptions = vscode.workspace.getConfiguration("rust-analyzer"); - if (workspace.kind == "Detached files") { + if (workspace.kind === "Detached Files") { initializationOptions = { "detachedFiles": workspace.files.map(file => file.uri.fsPath), ...initializationOptions }; } diff --git a/editors/code/src/ctx.ts b/editors/code/src/ctx.ts index dbfb9c6a1..22c5f62a1 100644 --- a/editors/code/src/ctx.ts +++ b/editors/code/src/ctx.ts @@ -9,12 +9,12 @@ import { ServerStatusParams } from './lsp_ext'; export type Workspace = { - kind: 'Workspace Folder', - folder: vscode.Uri, + kind: 'Workspace Folder'; + folder: vscode.Uri; } | { - kind: 'Detached files', - files: vscode.TextDocument[], + kind: 'Detached Files'; + files: vscode.TextDocument[]; }; export class Ctx { diff --git a/editors/code/src/main.ts b/editors/code/src/main.ts index 1a4af548d..b735186fe 100644 --- a/editors/code/src/main.ts +++ b/editors/code/src/main.ts @@ -47,9 +47,9 @@ async function tryActivate(context: vscode.ExtensionContext) { const workspaceFolder = vscode.workspace.workspaceFolders?.[0]; if (workspaceFolder === undefined) { - let rustDocuments = vscode.workspace.textDocuments.filter(document => isRustDocument(document)); + const rustDocuments = vscode.workspace.textDocuments.filter(document => isRustDocument(document)); if (rustDocuments.length > 0) { - ctx = await Ctx.create(config, context, serverPath, { kind: 'Detached files', files: rustDocuments }); + ctx = await Ctx.create(config, context, serverPath, { kind: 'Detached Files', files: rustDocuments }); } else { throw new Error("no rust files are opened"); } -- cgit v1.2.3