/ tests / strict_hover_range_test.rs
strict_hover_range_test.rs
  1  use ecolog_lsp::analysis::document::DocumentManager;
  2  use ecolog_lsp::analysis::query::QueryEngine;
  3  use ecolog_lsp::languages::LanguageRegistry;
  4  use std::sync::Arc;
  5  use tower_lsp::lsp_types::{Position, Url};
  6  
  7  async fn setup_manager() -> DocumentManager {
  8      let query_engine = Arc::new(QueryEngine::new());
  9      let mut registry = LanguageRegistry::new();
 10      registry.register(Arc::new(ecolog_lsp::languages::javascript::JavaScript));
 11      registry.register(Arc::new(ecolog_lsp::languages::typescript::TypeScript));
 12      registry.register(Arc::new(ecolog_lsp::languages::python::Python));
 13      registry.register(Arc::new(ecolog_lsp::languages::rust::Rust));
 14      registry.register(Arc::new(ecolog_lsp::languages::go::Go));
 15      let languages = Arc::new(registry);
 16      DocumentManager::new(query_engine, languages.clone())
 17  }
 18  
 19  #[tokio::test]
 20  async fn test_js_hover_only_on_var_name_dot_notation() {
 21      let doc_manager = setup_manager().await;
 22      let uri = Url::parse("file:///test.js").unwrap();
 23  
 24      let content = "const a = process.env.DB_URL;";
 25      doc_manager
 26          .open(uri.clone(), "javascript".into(), content.to_string(), 0)
 27          .await;
 28  
 29      let ref_on_process = doc_manager.get_env_reference_cloned(&uri, Position::new(0, 10));
 30      assert!(
 31          ref_on_process.is_none(),
 32          "Hover should NOT trigger on 'process'"
 33      );
 34  
 35      let ref_on_env = doc_manager.get_env_reference_cloned(&uri, Position::new(0, 18));
 36      assert!(ref_on_env.is_none(), "Hover should NOT trigger on 'env'");
 37  
 38      let ref_on_dot = doc_manager.get_env_reference_cloned(&uri, Position::new(0, 21));
 39      assert!(ref_on_dot.is_none(), "Hover should NOT trigger on '.'");
 40  
 41      let ref_on_var = doc_manager.get_env_reference_cloned(&uri, Position::new(0, 22));
 42      assert!(ref_on_var.is_some(), "Hover SHOULD trigger on 'DB_URL'");
 43      assert_eq!(ref_on_var.unwrap().name, "DB_URL");
 44  
 45      let ref_on_var_mid = doc_manager.get_env_reference_cloned(&uri, Position::new(0, 25));
 46      assert!(
 47          ref_on_var_mid.is_some(),
 48          "Hover SHOULD trigger in middle of 'DB_URL'"
 49      );
 50  }
 51  
 52  #[tokio::test]
 53  async fn test_js_hover_only_on_var_name_bracket_notation() {
 54      let doc_manager = setup_manager().await;
 55      let uri = Url::parse("file:///test.js").unwrap();
 56  
 57      let content = "const a = process.env['DB_URL'];";
 58      doc_manager
 59          .open(uri.clone(), "javascript".into(), content.to_string(), 0)
 60          .await;
 61  
 62      let ref_on_bracket = doc_manager.get_env_reference_cloned(&uri, Position::new(0, 21));
 63      assert!(ref_on_bracket.is_none(), "Hover should NOT trigger on '['");
 64  
 65      let ref_on_quote = doc_manager.get_env_reference_cloned(&uri, Position::new(0, 22));
 66      assert!(
 67          ref_on_quote.is_none(),
 68          "Hover should NOT trigger on opening quote"
 69      );
 70  
 71      let ref_on_var = doc_manager.get_env_reference_cloned(&uri, Position::new(0, 24));
 72      assert!(
 73          ref_on_var.is_some(),
 74          "Hover SHOULD trigger inside 'DB_URL' string"
 75      );
 76      assert_eq!(ref_on_var.unwrap().name, "DB_URL");
 77  }
 78  
 79  #[tokio::test]
 80  async fn test_ts_hover_only_on_var_name_process_env() {
 81      let doc_manager = setup_manager().await;
 82      let uri = Url::parse("file:///test.ts").unwrap();
 83  
 84      let content = "const a = process.env.VITE_API;";
 85      doc_manager
 86          .open(uri.clone(), "typescript".into(), content.to_string(), 0)
 87          .await;
 88  
 89      let ref_on_process = doc_manager.get_env_reference_cloned(&uri, Position::new(0, 12));
 90      assert!(
 91          ref_on_process.is_none(),
 92          "Hover should NOT trigger on 'process'"
 93      );
 94  
 95      let ref_on_env = doc_manager.get_env_reference_cloned(&uri, Position::new(0, 19));
 96      assert!(ref_on_env.is_none(), "Hover should NOT trigger on 'env'");
 97  
 98      let ref_on_var = doc_manager.get_env_reference_cloned(&uri, Position::new(0, 24));
 99      assert!(ref_on_var.is_some(), "Hover SHOULD trigger on 'VITE_API'");
100      assert_eq!(ref_on_var.unwrap().name, "VITE_API");
101  }
102  
103  #[tokio::test]
104  async fn test_py_hover_only_on_var_name_environ_subscript() {
105      let doc_manager = setup_manager().await;
106      let uri = Url::parse("file:///test.py").unwrap();
107  
108      let content = "import os\nx = os.environ['DB_URL']";
109      doc_manager
110          .open(uri.clone(), "python".into(), content.to_string(), 0)
111          .await;
112  
113      let ref_on_os = doc_manager.get_env_reference_cloned(&uri, Position::new(1, 5));
114      assert!(ref_on_os.is_none(), "Hover should NOT trigger on 'os'");
115  
116      let ref_on_environ = doc_manager.get_env_reference_cloned(&uri, Position::new(1, 9));
117      assert!(
118          ref_on_environ.is_none(),
119          "Hover should NOT trigger on 'environ'"
120      );
121  
122      let ref_on_bracket = doc_manager.get_env_reference_cloned(&uri, Position::new(1, 14));
123      assert!(ref_on_bracket.is_none(), "Hover should NOT trigger on '['");
124  
125      let ref_on_var = doc_manager.get_env_reference_cloned(&uri, Position::new(1, 18));
126      assert!(ref_on_var.is_some(), "Hover SHOULD trigger on 'DB_URL'");
127      assert_eq!(ref_on_var.unwrap().name, "DB_URL");
128  }
129  
130  #[tokio::test]
131  async fn test_py_hover_only_on_var_name_getenv() {
132      let doc_manager = setup_manager().await;
133      let uri = Url::parse("file:///test.py").unwrap();
134  
135      let content = "import os\nx = os.getenv('DB_URL')";
136      doc_manager
137          .open(uri.clone(), "python".into(), content.to_string(), 0)
138          .await;
139  
140      let ref_on_getenv = doc_manager.get_env_reference_cloned(&uri, Position::new(1, 8));
141      assert!(
142          ref_on_getenv.is_none(),
143          "Hover should NOT trigger on 'getenv'"
144      );
145  
146      let ref_on_var = doc_manager.get_env_reference_cloned(&uri, Position::new(1, 16));
147      assert!(ref_on_var.is_some(), "Hover SHOULD trigger on 'DB_URL'");
148      assert_eq!(ref_on_var.unwrap().name, "DB_URL");
149  }
150  
151  #[tokio::test]
152  async fn test_rust_hover_only_on_var_name_std_env_var() {
153      let doc_manager = setup_manager().await;
154      let uri = Url::parse("file:///test.rs").unwrap();
155  
156      let content = r#"fn main() { std::env::var("DB_URL"); }"#;
157      doc_manager
158          .open(uri.clone(), "rust".into(), content.to_string(), 0)
159          .await;
160  
161      let ref_on_std = doc_manager.get_env_reference_cloned(&uri, Position::new(0, 13));
162      assert!(ref_on_std.is_none(), "Hover should NOT trigger on 'std'");
163  
164      let ref_on_env = doc_manager.get_env_reference_cloned(&uri, Position::new(0, 18));
165      assert!(ref_on_env.is_none(), "Hover should NOT trigger on 'env'");
166  
167      let ref_on_var_fn = doc_manager.get_env_reference_cloned(&uri, Position::new(0, 23));
168      assert!(
169          ref_on_var_fn.is_none(),
170          "Hover should NOT trigger on 'var' function name"
171      );
172  
173      let ref_on_var = doc_manager.get_env_reference_cloned(&uri, Position::new(0, 28));
174      assert!(ref_on_var.is_some(), "Hover SHOULD trigger on 'DB_URL'");
175      assert_eq!(ref_on_var.unwrap().name, "DB_URL");
176  }
177  
178  #[tokio::test]
179  async fn test_rust_hover_only_on_var_name_env_macro() {
180      let doc_manager = setup_manager().await;
181      let uri = Url::parse("file:///test.rs").unwrap();
182  
183      let content = r#"fn main() { env!("DB_URL"); }"#;
184      doc_manager
185          .open(uri.clone(), "rust".into(), content.to_string(), 0)
186          .await;
187  
188      let ref_on_env = doc_manager.get_env_reference_cloned(&uri, Position::new(0, 13));
189      assert!(
190          ref_on_env.is_none(),
191          "Hover should NOT trigger on 'env' macro name"
192      );
193  
194      let ref_on_bang = doc_manager.get_env_reference_cloned(&uri, Position::new(0, 15));
195      assert!(ref_on_bang.is_none(), "Hover should NOT trigger on '!'");
196  
197      let ref_on_var = doc_manager.get_env_reference_cloned(&uri, Position::new(0, 19));
198      assert!(
199          ref_on_var.is_some(),
200          "Hover SHOULD trigger on 'DB_URL' in env! macro"
201      );
202      assert_eq!(ref_on_var.unwrap().name, "DB_URL");
203  }
204  
205  #[tokio::test]
206  async fn test_go_hover_only_on_var_name_getenv() {
207      let doc_manager = setup_manager().await;
208      let uri = Url::parse("file:///test.go").unwrap();
209  
210      let content = "package main\nimport \"os\"\nfunc main() {\n  val := os.Getenv(\"DB_URL\")\n}";
211      doc_manager
212          .open(uri.clone(), "go".into(), content.to_string(), 0)
213          .await;
214  
215      let ref_on_os = doc_manager.get_env_reference_cloned(&uri, Position::new(3, 10));
216      assert!(ref_on_os.is_none(), "Hover should NOT trigger on 'os'");
217  
218      let ref_on_getenv = doc_manager.get_env_reference_cloned(&uri, Position::new(3, 14));
219      assert!(
220          ref_on_getenv.is_none(),
221          "Hover should NOT trigger on 'Getenv'"
222      );
223  
224      let ref_on_var = doc_manager.get_env_reference_cloned(&uri, Position::new(3, 22));
225      assert!(ref_on_var.is_some(), "Hover SHOULD trigger on 'DB_URL'");
226      assert_eq!(ref_on_var.unwrap().name, "DB_URL");
227  }
228  
229  #[tokio::test]
230  async fn test_go_hover_only_on_var_name_lookupenv() {
231      let doc_manager = setup_manager().await;
232      let uri = Url::parse("file:///test.go").unwrap();
233  
234      let content =
235          "package main\nimport \"os\"\nfunc main() {\n  val, ok := os.LookupEnv(\"API_KEY\")\n}";
236      doc_manager
237          .open(uri.clone(), "go".into(), content.to_string(), 0)
238          .await;
239  
240      let ref_on_lookupenv = doc_manager.get_env_reference_cloned(&uri, Position::new(3, 18));
241      assert!(
242          ref_on_lookupenv.is_none(),
243          "Hover should NOT trigger on 'LookupEnv'"
244      );
245  
246      let ref_on_var = doc_manager.get_env_reference_cloned(&uri, Position::new(3, 28));
247      assert!(ref_on_var.is_some(), "Hover SHOULD trigger on 'API_KEY'");
248      assert_eq!(ref_on_var.unwrap().name, "API_KEY");
249  }
250  
251  #[tokio::test]
252  async fn test_js_no_hover_on_semicolon_after_var() {
253      let doc_manager = setup_manager().await;
254      let uri = Url::parse("file:///test.js").unwrap();
255  
256      let content = "const a = process.env.DB_URL;";
257      doc_manager
258          .open(uri.clone(), "javascript".into(), content.to_string(), 0)
259          .await;
260  
261      let ref_on_last_char = doc_manager.get_env_reference_cloned(&uri, Position::new(0, 27));
262      assert!(
263          ref_on_last_char.is_some(),
264          "Hover SHOULD trigger on last char of 'DB_URL'"
265      );
266  
267      let ref_on_semicolon = doc_manager.get_env_reference_cloned(&uri, Position::new(0, 28));
268      assert!(
269          ref_on_semicolon.is_none(),
270          "Hover should NOT trigger on ';' after variable"
271      );
272  }
273  
274  #[tokio::test]
275  async fn test_js_no_hover_on_closing_quote_bracket_notation() {
276      let doc_manager = setup_manager().await;
277      let uri = Url::parse("file:///test.js").unwrap();
278  
279      let content = "const a = process.env['DB_URL'];";
280      doc_manager
281          .open(uri.clone(), "javascript".into(), content.to_string(), 0)
282          .await;
283  
284      let ref_on_last_char = doc_manager.get_env_reference_cloned(&uri, Position::new(0, 28));
285      assert!(
286          ref_on_last_char.is_some(),
287          "Hover SHOULD trigger on last char of 'DB_URL'"
288      );
289  
290      let ref_on_quote = doc_manager.get_env_reference_cloned(&uri, Position::new(0, 29));
291      assert!(
292          ref_on_quote.is_none(),
293          "Hover should NOT trigger on closing quote"
294      );
295  
296      let ref_on_bracket = doc_manager.get_env_reference_cloned(&uri, Position::new(0, 30));
297      assert!(ref_on_bracket.is_none(), "Hover should NOT trigger on ']'");
298  }
299  
300  #[tokio::test]
301  async fn test_returned_range_is_name_range_not_full_range() {
302      let doc_manager = setup_manager().await;
303      let uri = Url::parse("file:///test.js").unwrap();
304  
305      let content = "const a = process.env.DB_URL;";
306      doc_manager
307          .open(uri.clone(), "javascript".into(), content.to_string(), 0)
308          .await;
309  
310      let ref_result = doc_manager.get_env_reference_cloned(&uri, Position::new(0, 24));
311      assert!(ref_result.is_some());
312      let reference = ref_result.unwrap();
313  
314      assert_eq!(reference.name_range.start.line, 0);
315      assert_eq!(reference.name_range.start.character, 22);
316      assert_eq!(reference.name_range.end.line, 0);
317      assert_eq!(reference.name_range.end.character, 28);
318  
319      assert_eq!(reference.full_range.start.line, 0);
320      assert_eq!(reference.full_range.start.character, 10);
321      assert_eq!(reference.full_range.end.line, 0);
322      assert_eq!(reference.full_range.end.character, 28);
323  }