diff --git a/crates/language_tools/src/lsp_button.rs b/crates/language_tools/src/lsp_button.rs index 781c18eb84cbc9ad7a1b666c089a7b65460c327b..59b14d470003f3a8a4f45b7b2b3e51505f562e56 100644 --- a/crates/language_tools/src/lsp_button.rs +++ b/crates/language_tools/src/lsp_button.rs @@ -230,7 +230,7 @@ impl LanguageServerState { ( server_id, ( - status.server_version.clone(), + status.server_readable_version.clone(), status.binary.as_ref().map(|b| b.path.clone()), status.process_id, ), diff --git a/crates/language_tools/src/lsp_log_view.rs b/crates/language_tools/src/lsp_log_view.rs index 47c840ea4e2f22e1b64cfc5b78bb7f983255dcba..ff1ec56b41ccf12ce6e497c21439aea5c97c3d39 100644 --- a/crates/language_tools/src/lsp_log_view.rs +++ b/crates/language_tools/src/lsp_log_view.rs @@ -1355,6 +1355,7 @@ impl ServerInfo { status: LanguageServerStatus { name: server.name(), server_version: server.version(), + server_readable_version: server.readable_version(), pending_work: Default::default(), has_pending_diagnostic_updates: false, progress_tokens: Default::default(), diff --git a/crates/lsp/src/lsp.rs b/crates/lsp/src/lsp.rs index 2e2318065292ffdc2ac39b577afc7a264d36473d..00fe0f59f1c71cd0c36e7f579b058191eff8f898 100644 --- a/crates/lsp/src/lsp.rs +++ b/crates/lsp/src/lsp.rs @@ -1306,6 +1306,29 @@ impl LanguageServer { self.version.clone() } + /// Get the readable version of the running language server. + pub fn readable_version(&self) -> Option { + match self.name().as_ref() { + "gopls" => { + // Gopls returns a detailed JSON object as its version string; we must parse it to extract the semantic version. + // Example: `{"GoVersion":"go1.26.0","Path":"golang.org/x/tools/gopls","Main":{},"Deps":[],"Settings":[],"Version":"v0.21.1"}` + self.version + .as_ref() + .and_then(|obj| { + #[derive(Deserialize)] + struct GoplsVersion<'a> { + #[serde(rename = "Version")] + version: &'a str, + } + let parsed: GoplsVersion = serde_json::from_str(obj.as_str()).ok()?; + Some(parsed.version.trim_start_matches("v").to_owned().into()) + }) + .or_else(|| self.version.clone()) + } + _ => self.version.clone(), + } + } + /// Get the process name of the running language server. pub fn process_name(&self) -> &str { &self.process_name diff --git a/crates/project/src/lsp_store.rs b/crates/project/src/lsp_store.rs index 25a614052789c85b8c418086e803b9b5cb9e6fae..4673bc1df19b72a60be7197af9ae364acd0933c2 100644 --- a/crates/project/src/lsp_store.rs +++ b/crates/project/src/lsp_store.rs @@ -4028,6 +4028,7 @@ pub enum LspStoreEvent { pub struct LanguageServerStatus { pub name: LanguageServerName, pub server_version: Option, + pub server_readable_version: Option, pub pending_work: BTreeMap, pub has_pending_diagnostic_updates: bool, pub progress_tokens: HashSet, @@ -8201,6 +8202,7 @@ impl LspStore { LanguageServerStatus { name, server_version: None, + server_readable_version: None, pending_work: Default::default(), has_pending_diagnostic_updates: false, progress_tokens: Default::default(), @@ -9391,6 +9393,7 @@ impl LspStore { LanguageServerStatus { name: server_name.clone(), server_version: None, + server_readable_version: None, pending_work: Default::default(), has_pending_diagnostic_updates: false, progress_tokens: Default::default(), @@ -11354,6 +11357,7 @@ impl LspStore { LanguageServerStatus { name: language_server.name(), server_version: language_server.version(), + server_readable_version: language_server.readable_version(), pending_work: Default::default(), has_pending_diagnostic_updates: false, progress_tokens: Default::default(),