backtrace_ls/lsp/
server.rs1use std::sync::Arc;
4
5#[cfg(unix)]
6use async_lsp::stdio::{PipeStdin, PipeStdout};
7use async_lsp::{
8 client_monitor::ClientProcessMonitorLayer,
9 concurrency::ConcurrencyLayer,
10 lsp_types::{
11 CodeActionKind, CodeActionOptions, CodeActionProviderCapability, DiagnosticOptions,
12 DiagnosticServerCapabilities, ExecuteCommandOptions, ServerCapabilities, ServerInfo,
13 TextDocumentSyncCapability, TextDocumentSyncKind, WorkDoneProgressOptions,
14 },
15 panic::CatchUnwindLayer,
16 router::Router,
17 server::LifecycleLayer,
18};
19use tower::ServiceBuilder;
20
21use super::{code_action, handlers, state::ServerState};
22use crate::error::LSError;
23
24#[must_use]
25pub fn server_capabilities() -> ServerCapabilities {
26 ServerCapabilities {
27 diagnostic_provider: Some(DiagnosticServerCapabilities::Options(DiagnosticOptions {
28 identifier: None,
29 inter_file_dependencies: false,
30 workspace_diagnostics: true,
31 work_done_progress_options: WorkDoneProgressOptions::default(),
32 })),
33 text_document_sync: Some(TextDocumentSyncCapability::Kind(TextDocumentSyncKind::NONE)),
34 code_action_provider: Some(CodeActionProviderCapability::Options(CodeActionOptions {
35 code_action_kinds: Some(vec![CodeActionKind::QUICKFIX]),
36 work_done_progress_options: WorkDoneProgressOptions::default(),
37 resolve_provider: None,
38 })),
39 execute_command_provider: Some(ExecuteCommandOptions {
40 commands: code_action::commands::all(),
41 work_done_progress_options: WorkDoneProgressOptions::default(),
42 }),
43 ..ServerCapabilities::default()
44 }
45}
46
47#[must_use]
48pub fn server_info() -> ServerInfo {
49 ServerInfo {
50 name: "backtrace-ls".to_string(),
51 version: Some(env!("CARGO_PKG_VERSION").to_string()),
52 }
53}
54
55pub async fn run() -> Result<(), LSError> {
57 let (server, _) = async_lsp::MainLoop::new_server(|client| {
58 let state = ServerState::new(client.clone());
59 let mut router = Router::new(Arc::clone(&state));
60
61 handlers::register_all(&mut router, &state);
62
63 ServiceBuilder::new()
64 .layer(LifecycleLayer::default())
65 .layer(CatchUnwindLayer::default())
66 .layer(ConcurrencyLayer::default())
67 .layer(ClientProcessMonitorLayer::new(client))
68 .service(router)
69 });
70
71 #[cfg(unix)]
72 let (stdin, stdout) = (
73 PipeStdin::lock_tokio().unwrap(),
74 PipeStdout::lock_tokio().unwrap(),
75 );
76
77 #[cfg(not(unix))]
78 let (stdin, stdout) = (
79 tokio_util::compat::TokioAsyncReadCompatExt::compat(tokio::io::stdin()),
80 tokio_util::compat::TokioAsyncWriteCompatExt::compat_write(tokio::io::stdout()),
81 );
82
83 server
84 .run_buffered(stdin, stdout)
85 .await
86 .map_err(|e| LSError::Generic(format!("LSP server error: {e}")))?;
87
88 Ok(())
89}