nvrim/diagnostics/filters/
related_info.rs1use color_eyre::eyre::Context;
7use nvim_oxi::Array;
8use nvim_oxi::Dictionary;
9use nvim_oxi::ObjectKind;
10use nvim_oxi::conversion::FromObject;
11use ytil_noxi::dict::DictionaryExt;
12
13use crate::diagnostics::filters::BufferWithPath;
14use crate::diagnostics::filters::DiagnosticsFilter;
15
16pub struct RelatedInfoFilter {
19 rel_infos: Vec<RelatedInfo>,
22}
23
24impl RelatedInfoFilter {
25 pub fn new(lsp_diags: &[Dictionary]) -> color_eyre::Result<Self> {
30 Ok(Self {
31 rel_infos: Self::get_related_infos(lsp_diags)?,
32 })
33 }
34
35 fn get_related_infos(lsp_diags: &[Dictionary]) -> color_eyre::Result<Vec<RelatedInfo>> {
40 let mut out = vec![];
41 for lsp_diag in lsp_diags {
42 let Some(lsp) = lsp_diag.get_dict(&["user_data", "lsp"])? else {
44 continue;
45 };
46 let rel_infos_key = "relatedInformation";
47 let Some(rel_infos) = lsp.get(rel_infos_key) else {
48 continue;
49 };
50
51 let rel_infos = Array::from_object(rel_infos.clone()).with_context(|| {
52 ytil_noxi::extract::unexpected_kind_error_msg(rel_infos, rel_infos_key, &lsp, ObjectKind::Array)
53 })?;
54 for rel_info in rel_infos {
55 let rel_info = Dictionary::try_from(rel_info)?;
56 out.push(RelatedInfo::from_related_info(&rel_info)?);
57 }
58 }
59 Ok(out)
60 }
61}
62
63impl DiagnosticsFilter for RelatedInfoFilter {
64 fn skip_diagnostic(&self, _buf: &BufferWithPath, lsp_diag: &Dictionary) -> color_eyre::Result<bool> {
69 if self.rel_infos.is_empty() {
70 return Ok(false);
71 }
72 let rel_info = RelatedInfo::from_lsp_diagnostic(lsp_diag)?;
74 if self.rel_infos.contains(&rel_info) {
75 return Ok(true);
76 }
77 Ok(false)
78 }
79}
80
81#[derive(Eq, PartialEq)]
83struct RelatedInfo {
84 col: i64,
86 end_col: i64,
88 end_lnum: i64,
90 lnum: i64,
92 message: String,
94}
95
96impl RelatedInfo {
97 fn from_lsp_diagnostic(lsp_diagnostic: &Dictionary) -> color_eyre::Result<Self> {
102 Ok(Self {
103 message: lsp_diagnostic.get_t::<nvim_oxi::String>("message")?,
104 lnum: lsp_diagnostic.get_t::<nvim_oxi::Integer>("lnum")?,
105 col: lsp_diagnostic.get_t::<nvim_oxi::Integer>("col")?,
106 end_lnum: lsp_diagnostic.get_t::<nvim_oxi::Integer>("end_lnum")?,
107 end_col: lsp_diagnostic.get_t::<nvim_oxi::Integer>("end_col")?,
108 })
109 }
110
111 fn from_related_info(rel_info: &Dictionary) -> color_eyre::Result<Self> {
116 let (start, end) = {
117 let range_query = ["location", "range"];
118 let range = rel_info.get_required_dict(&range_query)?;
119
120 let start_query = ["start"];
121 let end_query = ["end"];
122 (
123 range.get_required_dict(&start_query)?,
124 range.get_required_dict(&end_query)?,
125 )
126 };
127
128 Ok(Self {
129 message: rel_info.get_t::<nvim_oxi::String>("message")?,
130 lnum: start.get_t::<nvim_oxi::Integer>("line")?,
131 col: start.get_t::<nvim_oxi::Integer>("character")?,
132 end_lnum: end.get_t::<nvim_oxi::Integer>("line")?,
133 end_col: end.get_t::<nvim_oxi::Integer>("character")?,
134 })
135 }
136}