diff --git a/crates/rust-analyzer/src/diagnostics/to_proto.rs b/crates/rust-analyzer/src/diagnostics/to_proto.rs index 93bef5c8b4..d3720de33e 100644 --- a/crates/rust-analyzer/src/diagnostics/to_proto.rs +++ b/crates/rust-analyzer/src/diagnostics/to_proto.rs @@ -2,7 +2,7 @@ //! `cargo check` json format to the LSP diagnostic format. use std::{collections::HashMap, path::Path}; -use flycheck::{Applicability, DiagnosticLevel, DiagnosticSpan}; +use flycheck::{Applicability, DiagnosticCode, DiagnosticLevel, DiagnosticSpan}; use stdx::format_to; use crate::{lsp_ext, to_proto::url_from_abs_path}; @@ -211,6 +211,8 @@ pub(crate) fn map_rust_diagnostic_to_lsp( } } + let code_description = rustc_code_description(rd.code.as_ref()); + primary_spans .iter() .map(|primary_span| { @@ -248,7 +250,7 @@ pub(crate) fn map_rust_diagnostic_to_lsp( range: in_macro_location.range, severity, code: code.clone().map(lsp_types::NumberOrString::String), - code_description: None, + code_description: code_description.clone(), source: Some(source.clone()), message: message.clone(), related_information: Some(information_for_additional_diagnostic), @@ -269,7 +271,7 @@ pub(crate) fn map_rust_diagnostic_to_lsp( range: location.range, severity, code: code.clone().map(lsp_types::NumberOrString::String), - code_description: None, + code_description: code_description.clone(), source: Some(source.clone()), message, related_information: if related_information.is_empty() { @@ -292,6 +294,20 @@ pub(crate) fn map_rust_diagnostic_to_lsp( .collect() } +fn rustc_code_description(code: Option<&DiagnosticCode>) -> Option { + code.filter(|c| { + let mut chars = c.code.chars(); + chars.next().map_or(false, |c| c == 'E') + && chars.by_ref().take(4).all(|c| c.is_ascii_digit()) + && chars.next().is_none() + }) + .and_then(|c| { + lsp_types::Url::parse(&format!("https://doc.rust-lang.org/error-index.html#{}", c.code)) + .ok() + .map(|href| lsp_types::CodeDescription { href }) + }) +} + #[cfg(test)] #[cfg(not(windows))] mod tests {