ricecoder_external_lsp/mapping/
hover.rs1use crate::error::Result;
7use crate::types::HoverMappingRules;
8use serde_json::Value;
9
10use super::transformer::OutputTransformer;
11
12#[derive(Debug, Clone)]
14pub struct HoverMapper {
15 transformer: OutputTransformer,
16}
17
18impl HoverMapper {
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: &HoverMappingRules) -> Result<Value> {
42 self.transformer.transform_hover(response, rules)
43 }
44
45 pub fn map_content(&self, content: &Value, rules: &HoverMappingRules) -> Result<Value> {
50 let wrapped = serde_json::json!({
52 "result": {
53 "contents": content
54 }
55 });
56
57 let default_rules = HoverMappingRules {
59 content_path: "$.result.contents".to_string(),
60 field_mappings: rules.field_mappings.clone(),
61 transform: rules.transform.clone(),
62 };
63
64 self.transformer.transform_hover(&wrapped, &default_rules)
65 }
66}
67
68impl Default for HoverMapper {
69 fn default() -> Self {
70 Self::new()
71 }
72}
73
74#[cfg(test)]
75mod tests {
76 use super::*;
77 use std::collections::HashMap;
78
79 #[test]
80 fn test_map_hover_response() {
81 let mapper = HoverMapper::new();
82 let response = serde_json::json!({
83 "result": {
84 "contents": {
85 "language": "rust",
86 "value": "fn foo() -> i32"
87 }
88 }
89 });
90
91 let mut field_mappings = HashMap::new();
92 field_mappings.insert("language".to_string(), "$.language".to_string());
93 field_mappings.insert("value".to_string(), "$.value".to_string());
94
95 let rules = HoverMappingRules {
96 content_path: "$.result.contents".to_string(),
97 field_mappings,
98 transform: None,
99 };
100
101 let result = mapper.map(&response, &rules).unwrap();
102 assert_eq!(result["language"], "rust");
103 assert_eq!(result["value"], "fn foo() -> i32");
104 }
105
106 #[test]
107 fn test_map_hover_with_custom_structure() {
108 let mapper = HoverMapper::new();
109 let response = serde_json::json!({
110 "hover_info": {
111 "doc": "A function that returns an integer",
112 "signature": "fn foo() -> i32"
113 }
114 });
115
116 let mut field_mappings = HashMap::new();
117 field_mappings.insert("documentation".to_string(), "$.doc".to_string());
118 field_mappings.insert("signature".to_string(), "$.signature".to_string());
119
120 let rules = HoverMappingRules {
121 content_path: "$.hover_info".to_string(),
122 field_mappings,
123 transform: None,
124 };
125
126 let result = mapper.map(&response, &rules).unwrap();
127 assert_eq!(result["documentation"], "A function that returns an integer");
128 assert_eq!(result["signature"], "fn foo() -> i32");
129 }
130
131 #[test]
132 fn test_map_hover_content() {
133 let mapper = HoverMapper::new();
134 let content = serde_json::json!({
135 "language": "python",
136 "value": "def bar(): pass"
137 });
138
139 let mut field_mappings = HashMap::new();
140 field_mappings.insert("language".to_string(), "$.language".to_string());
141 field_mappings.insert("value".to_string(), "$.value".to_string());
142
143 let rules = HoverMappingRules {
144 content_path: "$.result.contents".to_string(),
145 field_mappings,
146 transform: None,
147 };
148
149 let result = mapper.map_content(&content, &rules).unwrap();
150 assert_eq!(result["language"], "python");
151 assert_eq!(result["value"], "def bar(): pass");
152 }
153
154 #[test]
155 fn test_map_hover_with_markdown() {
156 let mapper = HoverMapper::new();
157 let response = serde_json::json!({
158 "result": {
159 "contents": {
160 "kind": "markdown",
161 "value": "# Function\n\nThis is a function"
162 }
163 }
164 });
165
166 let mut field_mappings = HashMap::new();
167 field_mappings.insert("kind".to_string(), "$.kind".to_string());
168 field_mappings.insert("value".to_string(), "$.value".to_string());
169
170 let rules = HoverMappingRules {
171 content_path: "$.result.contents".to_string(),
172 field_mappings,
173 transform: None,
174 };
175
176 let result = mapper.map(&response, &rules).unwrap();
177 assert_eq!(result["kind"], "markdown");
178 assert!(result["value"].as_str().unwrap().contains("Function"));
179 }
180
181 #[test]
182 fn test_map_hover_missing_field() {
183 let mapper = HoverMapper::new();
184 let response = serde_json::json!({
185 "result": {
186 "contents": {
187 "value": "fn foo() -> i32"
188 }
189 }
190 });
191
192 let mut field_mappings = HashMap::new();
193 field_mappings.insert("language".to_string(), "$.language".to_string()); field_mappings.insert("value".to_string(), "$.value".to_string());
195
196 let rules = HoverMappingRules {
197 content_path: "$.result.contents".to_string(),
198 field_mappings,
199 transform: None,
200 };
201
202 let result = mapper.map(&response, &rules).unwrap();
203 assert_eq!(result["value"], "fn foo() -> i32");
204 assert!(!result.get("language").is_some() || result["language"].is_null());
206 }
207}