deps_lsp/handlers/
hover.rs1use crate::config::DepsConfig;
4use crate::document::{ServerState, ensure_document_loaded};
5use std::sync::Arc;
6use tokio::sync::RwLock;
7use tower_lsp_server::Client;
8use tower_lsp_server::ls_types::{Hover, HoverParams};
9
10pub async fn handle_hover(
12 state: Arc<ServerState>,
13 params: HoverParams,
14 client: Client,
15 config: Arc<RwLock<DepsConfig>>,
16) -> Option<Hover> {
17 let uri = ¶ms.text_document_position_params.text_document.uri;
18 let position = params.text_document_position_params.position;
19
20 if !ensure_document_loaded(uri, Arc::clone(&state), client, config).await {
22 tracing::warn!("Could not load document for hover: {:?}", uri);
23 return None;
24 }
25
26 let doc = state.get_document(uri)?;
28 let ecosystem = state.ecosystem_registry.get(doc.ecosystem_id)?;
29 let parse_result = doc.parse_result()?;
30
31 ecosystem
33 .generate_hover(
34 parse_result,
35 position,
36 &doc.cached_versions,
37 &doc.resolved_versions,
38 )
39 .await
40}
41
42#[cfg(test)]
43mod tests {
44 use super::*;
45 use crate::document::ServerState;
46 use crate::test_utils::test_helpers::create_test_client_and_config;
47 use tower_lsp_server::ls_types::{
48 Position, TextDocumentIdentifier, TextDocumentPositionParams, Uri,
49 };
50
51 #[tokio::test]
54 async fn test_handle_hover_missing_document() {
55 let state = Arc::new(ServerState::new());
56 let uri = Uri::from_file_path("/test/Cargo.toml").unwrap();
57 let (client, config) = create_test_client_and_config();
58
59 let params = HoverParams {
60 text_document_position_params: TextDocumentPositionParams {
61 text_document: TextDocumentIdentifier { uri },
62 position: Position::new(0, 0),
63 },
64 work_done_progress_params: Default::default(),
65 };
66
67 let result = handle_hover(state, params, client, config).await;
68 assert!(result.is_none());
69 }
70
71 #[cfg(feature = "cargo")]
73 mod cargo_tests {
74 use super::*;
75 use crate::document::{DocumentState, Ecosystem};
76
77 #[tokio::test]
78 async fn test_handle_hover() {
79 let state = Arc::new(ServerState::new());
80 let uri = Uri::from_file_path("/test/Cargo.toml").unwrap();
81
82 let ecosystem = state.ecosystem_registry.get("cargo").unwrap();
83 let content = r#"[dependencies]
84serde = "1.0.0"
85"#
86 .to_string();
87
88 let parse_result = ecosystem
89 .parse_manifest(&content, &uri)
90 .await
91 .expect("Failed to parse manifest");
92
93 let doc_state = DocumentState::new_from_parse_result("cargo", content, parse_result);
94 state.update_document(uri.clone(), doc_state);
95
96 let params = HoverParams {
97 text_document_position_params: TextDocumentPositionParams {
98 text_document: TextDocumentIdentifier { uri },
99 position: Position::new(1, 0),
100 },
101 work_done_progress_params: Default::default(),
102 };
103
104 let (client, config) = create_test_client_and_config();
105 let _result = handle_hover(state, params, client, config).await;
106 }
108
109 #[tokio::test]
110 async fn test_handle_hover_no_parse_result() {
111 let state = Arc::new(ServerState::new());
112 let uri = Uri::from_file_path("/test/Cargo.toml").unwrap();
113
114 let doc_state = DocumentState::new(Ecosystem::Cargo, String::new(), vec![]);
115 state.update_document(uri.clone(), doc_state);
116
117 let params = HoverParams {
118 text_document_position_params: TextDocumentPositionParams {
119 text_document: TextDocumentIdentifier { uri },
120 position: Position::new(0, 0),
121 },
122 work_done_progress_params: Default::default(),
123 };
124
125 let (client, config) = create_test_client_and_config();
126 let result = handle_hover(state, params, client, config).await;
127 assert!(result.is_none());
128 }
129 }
130
131 #[cfg(feature = "npm")]
133 mod npm_tests {
134 use super::*;
135 use crate::document::DocumentState;
136
137 #[tokio::test]
138 async fn test_handle_hover() {
139 let state = Arc::new(ServerState::new());
140 let uri = Uri::from_file_path("/test/package.json").unwrap();
141
142 let ecosystem = state.ecosystem_registry.get("npm").unwrap();
143 let content = r#"{"dependencies": {"express": "4.0.0"}}"#.to_string();
144
145 let parse_result = ecosystem
146 .parse_manifest(&content, &uri)
147 .await
148 .expect("Failed to parse manifest");
149
150 let doc_state = DocumentState::new_from_parse_result("npm", content, parse_result);
151 state.update_document(uri.clone(), doc_state);
152
153 let params = HoverParams {
154 text_document_position_params: TextDocumentPositionParams {
155 text_document: TextDocumentIdentifier { uri },
156 position: Position::new(0, 20),
157 },
158 work_done_progress_params: Default::default(),
159 };
160
161 let (client, config) = create_test_client_and_config();
162 let _result = handle_hover(state, params, client, config).await;
163 }
165 }
166}