ricecoder_external_lsp/mapping/
diagnostics.rs1use crate::error::Result;
7use crate::types::DiagnosticsMappingRules;
8use serde_json::Value;
9
10use super::transformer::OutputTransformer;
11
12#[derive(Debug, Clone)]
14pub struct DiagnosticsMapper {
15 transformer: OutputTransformer,
16}
17
18impl DiagnosticsMapper {
19 pub fn new() -> Self {
21 Self {
22 transformer: OutputTransformer::new(),
23 }
24 }
25
26 pub fn with_transformer(transformer: OutputTransformer) -> Self {
28 Self { transformer }
29 }
30
31 pub fn map(&self, response: &Value, rules: &DiagnosticsMappingRules) -> Result<Vec<Value>> {
42 self.transformer.transform_diagnostics(response, rules)
43 }
44
45 pub fn map_item(&self, item: &Value, rules: &DiagnosticsMappingRules) -> Result<Value> {
50 let wrapped = serde_json::json!({
52 "result": {
53 "items": [item]
54 }
55 });
56
57 let default_rules = DiagnosticsMappingRules {
59 items_path: "$.result.items".to_string(),
60 field_mappings: rules.field_mappings.clone(),
61 transform: rules.transform.clone(),
62 };
63
64 let results = self.transformer.transform_diagnostics(&wrapped, &default_rules)?;
65
66 if results.is_empty() {
67 return Err(crate::error::ExternalLspError::TransformationError(
68 "Failed to map diagnostic item".to_string(),
69 ));
70 }
71
72 Ok(results[0].clone())
73 }
74}
75
76impl Default for DiagnosticsMapper {
77 fn default() -> Self {
78 Self::new()
79 }
80}
81
82#[cfg(test)]
83mod tests {
84 use super::*;
85 use std::collections::HashMap;
86
87 #[test]
88 fn test_map_diagnostics_response() {
89 let mapper = DiagnosticsMapper::new();
90 let response = serde_json::json!({
91 "result": [
92 {
93 "message": "error: undefined variable",
94 "range": {"start": {"line": 1, "character": 0}, "end": {"line": 1, "character": 5}},
95 "severity": 1
96 },
97 {
98 "message": "warning: unused variable",
99 "range": {"start": {"line": 2, "character": 0}, "end": {"line": 2, "character": 3}},
100 "severity": 2
101 }
102 ]
103 });
104
105 let mut field_mappings = HashMap::new();
106 field_mappings.insert("message".to_string(), "$.message".to_string());
107 field_mappings.insert("range".to_string(), "$.range".to_string());
108 field_mappings.insert("severity".to_string(), "$.severity".to_string());
109
110 let rules = DiagnosticsMappingRules {
111 items_path: "$.result".to_string(),
112 field_mappings,
113 transform: None,
114 };
115
116 let results = mapper.map(&response, &rules).unwrap();
117 assert_eq!(results.len(), 2);
118 assert_eq!(results[0]["message"], "error: undefined variable");
119 assert_eq!(results[1]["message"], "warning: unused variable");
120 }
121
122 #[test]
123 fn test_map_diagnostics_with_custom_structure() {
124 let mapper = DiagnosticsMapper::new();
125 let response = serde_json::json!({
126 "issues": [
127 {"error_message": "error", "error_line": 1},
128 {"error_message": "warning", "error_line": 2}
129 ]
130 });
131
132 let mut field_mappings = HashMap::new();
133 field_mappings.insert("message".to_string(), "$.error_message".to_string());
134 field_mappings.insert("line".to_string(), "$.error_line".to_string());
135
136 let rules = DiagnosticsMappingRules {
137 items_path: "$.issues".to_string(),
138 field_mappings,
139 transform: None,
140 };
141
142 let results = mapper.map(&response, &rules).unwrap();
143 assert_eq!(results.len(), 2);
144 assert_eq!(results[0]["message"], "error");
145 assert_eq!(results[0]["line"], 1);
146 }
147
148 #[test]
149 fn test_map_single_diagnostic() {
150 let mapper = DiagnosticsMapper::new();
151 let item = serde_json::json!({
152 "message": "test error",
153 "severity": 1,
154 "range": {"start": {"line": 0, "character": 0}}
155 });
156
157 let mut field_mappings = HashMap::new();
158 field_mappings.insert("message".to_string(), "$.message".to_string());
159 field_mappings.insert("severity".to_string(), "$.severity".to_string());
160
161 let rules = DiagnosticsMappingRules {
162 items_path: "$.result.items".to_string(),
163 field_mappings,
164 transform: None,
165 };
166
167 let result = mapper.map_item(&item, &rules).unwrap();
168 assert_eq!(result["message"], "test error");
169 assert_eq!(result["severity"], 1);
170 }
171
172 #[test]
173 fn test_map_empty_diagnostics() {
174 let mapper = DiagnosticsMapper::new();
175 let response = serde_json::json!({
176 "result": []
177 });
178
179 let field_mappings = HashMap::new();
180 let rules = DiagnosticsMappingRules {
181 items_path: "$.result".to_string(),
182 field_mappings,
183 transform: None,
184 };
185
186 let results = mapper.map(&response, &rules).unwrap();
187 assert_eq!(results.len(), 0);
188 }
189}