Skip to content

Commit 5bfdb8c

Browse files
committed
chore: migrate from tower-lsp to tower-lsp-server
Upgrade the LSP implementation to use the tower-lsp-server crate, which provides better maintenance and updated APIs.
1 parent 70d723c commit 5bfdb8c

9 files changed

Lines changed: 46 additions & 39 deletions

File tree

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ tabled = "0.20.0"
3131
terminal_size = "0.4.3"
3232
clap = { version = "4.5.60", features = ["cargo", "derive"] }
3333
chrono = { version = "0.4.44", features = ["serde"] }
34-
tower-lsp = "0.20"
34+
tower-lsp-server = "0.23.0"
3535
tokio = { version = "1.49.0", features = ["full"] }
3636
url = "2.5.8"
3737

ci/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ default = ["termlog"]
2121
termlog = ["codeinput/termlog"]
2222
journald = ["codeinput/journald"]
2323
syslog = ["codeinput/syslog"]
24-
lsp = ["codeinput/tower-lsp", "codeinput/tokio", "tokio"]
24+
lsp = ["codeinput/tower-lsp-server", "codeinput/tokio", "tokio"]
2525

2626
[dependencies]
2727
codeinput = { version = "0.1.0", path = "../codeinput" }

codeinput/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ tabled = { workspace = true, optional = true }
9494
terminal_size = { workspace = true, optional = true }
9595
clap = { workspace = true, optional = true }
9696
chrono = { version = "0.4.44", features = ["serde"], optional = true }
97-
tower-lsp = { workspace = true, optional = true }
97+
tower-lsp-server = { workspace = true, optional = true }
9898
tokio = { workspace = true, optional = true }
9999
url = { workspace = true, optional = true }
100100

codeinput/src/core/commands/lsp.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,11 @@
44
55
use crate::utils::error::Result;
66

7-
#[cfg(feature = "tower-lsp")]
7+
#[cfg(feature = "tower-lsp-server")]
88
use crate::lsp::server::{run_lsp_server, run_lsp_server_tcp};
99

1010
/// Run the LSP server
11-
#[cfg(feature = "tower-lsp")]
11+
#[cfg(feature = "tower-lsp-server")]
1212
pub fn run(port: Option<u16>) -> Result<()> {
1313
let rt = tokio::runtime::Runtime::new()?;
1414
rt.block_on(async {

codeinput/src/core/commands/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,5 @@ pub mod list_rules;
77
pub mod list_tags;
88
pub mod parse;
99

10-
#[cfg(feature = "tower-lsp")]
10+
#[cfg(feature = "tower-lsp-server")]
1111
pub mod lsp;

codeinput/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,5 +12,5 @@ pub mod core;
1212
pub mod utils;
1313

1414
// LSP server module (requires full features - not just types)
15-
#[cfg(all(not(feature = "types"), feature = "tokio", feature = "tower-lsp"))]
15+
#[cfg(all(not(feature = "types"), feature = "tokio", feature = "tower-lsp-server"))]
1616
pub mod lsp;

codeinput/src/lsp/commands.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use tower_lsp::jsonrpc::Result as LspResult;
1+
use tower_lsp_server::jsonrpc::Result as LspResult;
22
use url::Url;
33

44
use crate::core::types::{CodeownersCache, OwnerType};
@@ -9,7 +9,7 @@ use super::types::*;
99
impl LspServer {
1010
pub async fn get_file_ownership_command(&self, uri_str: String) -> LspResult<Option<FileOwnershipInfo>> {
1111
let Ok(uri) = Url::parse(&uri_str) else {
12-
return Err(tower_lsp::jsonrpc::Error::invalid_params("Invalid URI"));
12+
return Err(tower_lsp_server::jsonrpc::Error::invalid_params("Invalid URI"));
1313
};
1414
Ok(self.get_file_ownership(&uri).await)
1515
}

codeinput/src/lsp/handlers.rs

Lines changed: 29 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,20 @@
11
use serde::Serialize;
22
use serde_json::Value;
3-
use tower_lsp::LanguageServer;
4-
use tower_lsp::jsonrpc::Result as LspResult;
5-
use tower_lsp::lsp_types::*;
3+
use tower_lsp_server::LanguageServer;
4+
use tower_lsp_server::jsonrpc::Result as LspResult;
5+
use tower_lsp_server::ls_types::*;
66
use url::Url;
77

88
use super::server::{LspServer, is_codeowners_file, uri_to_path};
99

10-
#[tower_lsp::async_trait]
1110
impl LanguageServer for LspServer {
1211
async fn initialize(&self, params: InitializeParams) -> LspResult<InitializeResult> {
1312
// Initialize workspaces from workspace folders
1413
let workspace_folders = params.workspace_folders.unwrap_or_default();
1514

1615
for folder in workspace_folders {
17-
if let Err(e) = self.initialize_workspace(folder.uri, None).await {
16+
let Ok(uri_url) = Url::parse(folder.uri.as_str()) else { continue; };
17+
if let Err(e) = self.initialize_workspace(uri_url, None).await {
1818
self.client
1919
.log_message(
2020
MessageType::WARNING,
@@ -25,18 +25,23 @@ impl LanguageServer for LspServer {
2525
}
2626

2727
// If no workspace folders, try to use root_uri
28-
if let Some(root_uri) = params.root_uri {
29-
if let Err(e) = self.initialize_workspace(root_uri, None).await {
30-
self.client
31-
.log_message(
32-
MessageType::WARNING,
33-
format!("Failed to initialize root workspace: {}", e),
34-
)
35-
.await;
28+
#[allow(deprecated)]
29+
let root_uri = params.root_uri;
30+
if let Some(root_uri) = root_uri {
31+
if let Ok(uri_url) = Url::parse(root_uri.as_str()) {
32+
if let Err(e) = self.initialize_workspace(uri_url, None).await {
33+
self.client
34+
.log_message(
35+
MessageType::WARNING,
36+
format!("Failed to initialize root workspace: {}", e),
37+
)
38+
.await;
39+
}
3640
}
3741
}
3842

3943
Ok(InitializeResult {
44+
offset_encoding: None,
4045
capabilities: ServerCapabilities {
4146
text_document_sync: Some(TextDocumentSyncCapability::Kind(
4247
TextDocumentSyncKind::FULL,
@@ -87,7 +92,7 @@ impl LanguageServer for LspServer {
8792
}
8893

8994
async fn did_open(&self, params: DidOpenTextDocumentParams) {
90-
let file_uri = params.text_document.uri;
95+
let Ok(file_uri) = Url::parse(params.text_document.uri.as_str()) else { return; };
9196

9297
// Check if this is a CODEOWNERS file and refresh cache if so
9398
if is_codeowners_file(&file_uri) {
@@ -120,7 +125,7 @@ impl LanguageServer for LspServer {
120125
}
121126

122127
async fn did_save(&self, params: DidSaveTextDocumentParams) {
123-
let file_uri = params.text_document.uri;
128+
let Ok(file_uri) = Url::parse(params.text_document.uri.as_str()) else { return; };
124129

125130
// If CODEOWNERS file was saved, refresh the cache
126131
if is_codeowners_file(&file_uri) {
@@ -147,7 +152,7 @@ impl LanguageServer for LspServer {
147152
}
148153

149154
async fn hover(&self, params: HoverParams) -> LspResult<Option<Hover>> {
150-
let file_uri = params.text_document_position_params.text_document.uri;
155+
let Ok(file_uri) = Url::parse(params.text_document_position_params.text_document.uri.as_str()) else { return Ok(None); };
151156

152157
// Get ownership info for this file
153158
if let Some(info) = self.get_file_ownership(&file_uri).await {
@@ -194,7 +199,7 @@ impl LanguageServer for LspServer {
194199
}
195200

196201
async fn code_lens(&self, params: CodeLensParams) -> LspResult<Option<Vec<CodeLens>>> {
197-
let file_uri = params.text_document.uri;
202+
let Ok(file_uri) = Url::parse(params.text_document.uri.as_str()) else { return Ok(None); };
198203

199204
// Get ownership info for this file
200205
if let Some(info) = self.get_file_ownership(&file_uri).await {
@@ -267,7 +272,7 @@ impl LanguageServer for LspServer {
267272
}
268273

269274
async fn inlay_hint(&self, params: InlayHintParams) -> LspResult<Option<Vec<InlayHint>>> {
270-
let file_uri = params.text_document.uri;
275+
let Ok(file_uri) = Url::parse(params.text_document.uri.as_str()) else { return Ok(None); };
271276

272277
let path = uri_to_path(&file_uri);
273278
let file_path = match path {
@@ -358,7 +363,7 @@ impl LanguageServer for LspServer {
358363

359364
async fn did_change_workspace_folders(&self, params: DidChangeWorkspaceFoldersParams) {
360365
// Handle removed workspaces - collect URIs first, then remove them
361-
let removed_uris: Vec<Url> = params.event.removed.iter().map(|f| f.uri.clone()).collect();
366+
let removed_uris: Vec<Url> = params.event.removed.iter().filter_map(|f| Url::parse(f.uri.as_str()).ok()).collect();
362367
{
363368
let mut workspaces = self.workspaces.write().await;
364369
for uri in removed_uris {
@@ -368,7 +373,8 @@ impl LanguageServer for LspServer {
368373

369374
// Handle added workspaces
370375
for folder in params.event.added {
371-
if let Err(e) = self.initialize_workspace(folder.uri, None).await {
376+
let Ok(uri_url) = Url::parse(folder.uri.as_str()) else { continue; };
377+
if let Err(e) = self.initialize_workspace(uri_url, None).await {
372378
self.client
373379
.log_message(
374380
MessageType::WARNING,
@@ -382,7 +388,7 @@ impl LanguageServer for LspServer {
382388
async fn execute_command(&self, params: ExecuteCommandParams) -> LspResult<Option<Value>> {
383389
fn to_value<T: Serialize>(v: T) -> LspResult<Value> {
384390
serde_json::to_value(v)
385-
.map_err(|e| tower_lsp::jsonrpc::Error::invalid_params(e.to_string()))
391+
.map_err(|e| tower_lsp_server::jsonrpc::Error::invalid_params(e.to_string()))
386392
}
387393

388394
match params.command.as_str() {
@@ -392,7 +398,7 @@ impl LanguageServer for LspServer {
392398
.first()
393399
.and_then(|v| v.as_str())
394400
.ok_or_else(|| {
395-
tower_lsp::jsonrpc::Error::invalid_params(
401+
tower_lsp_server::jsonrpc::Error::invalid_params(
396402
"Expected a single URI string argument",
397403
)
398404
})?;
@@ -411,7 +417,7 @@ impl LanguageServer for LspServer {
411417
let result = self.list_tags(None).await?;
412418
to_value(result).map(Some)
413419
}
414-
_ => Err(tower_lsp::jsonrpc::Error::method_not_found()),
420+
_ => Err(tower_lsp_server::jsonrpc::Error::method_not_found()),
415421
}
416422
}
417423
}

codeinput/src/lsp/server.rs

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@ use std::path::PathBuf;
33
use std::sync::Arc;
44

55
use tokio::sync::RwLock;
6-
use tower_lsp::lsp_types::*;
7-
use tower_lsp::Client;
6+
use tower_lsp_server::ls_types::*;
7+
use tower_lsp_server::Client;
88
use url::Url;
99

1010
use crate::core::cache::sync_cache;
@@ -138,8 +138,9 @@ impl LspServer {
138138

139139
// Publish diagnostics for this workspace
140140
for (file_uri, file_diagnostics) in diagnostics {
141+
let Ok(ls_uri) = file_uri.as_str().parse::<Uri>() else { continue; };
141142
self.client
142-
.publish_diagnostics(file_uri, file_diagnostics, None)
143+
.publish_diagnostics(ls_uri, file_diagnostics, None)
143144
.await;
144145
}
145146
}
@@ -163,9 +164,9 @@ pub async fn run_lsp_server() -> Result<()> {
163164
let stdin = tokio::io::stdin();
164165
let stdout = tokio::io::stdout();
165166

166-
let (service, socket) = tower_lsp::LspService::new(|client| LspServer::new(client));
167+
let (service, socket) = tower_lsp_server::LspService::new(|client| LspServer::new(client));
167168

168-
tower_lsp::Server::new(stdin, stdout, socket)
169+
tower_lsp_server::Server::new(stdin, stdout, socket)
169170
.serve(service)
170171
.await;
171172

@@ -184,8 +185,8 @@ pub async fn run_lsp_server_tcp(port: u16) -> Result<()> {
184185
loop {
185186
let (stream, _) = listener.accept().await?;
186187
let (read, write) = tokio::io::split(stream);
187-
let (service, socket) = tower_lsp::LspService::new(|client| LspServer::new(client));
188+
let (service, socket) = tower_lsp_server::LspService::new(|client| LspServer::new(client));
188189

189-
tokio::spawn(tower_lsp::Server::new(read, write, socket).serve(service));
190+
tokio::spawn(tower_lsp_server::Server::new(read, write, socket).serve(service));
190191
}
191192
}

0 commit comments

Comments
 (0)