searchfox_lib/
definition.rs1use crate::client::SearchfoxClient;
2use crate::search::SearchOptions;
3use crate::utils::extract_complete_method;
4use anyhow::Result;
5use log::{debug, error};
6
7impl SearchfoxClient {
8 pub async fn get_definition_context(
9 &self,
10 file_path: &str,
11 line_number: usize,
12 context_lines: usize,
13 ) -> Result<String> {
14 let file_content = self.get_file(file_path).await?;
15 let lines: Vec<&str> = file_content.lines().collect();
16
17 let (_, method_lines) = extract_complete_method(&lines, line_number);
18
19 if method_lines.len() > 1 {
20 return Ok(method_lines.join("\n"));
21 }
22
23 let start_line = if line_number > context_lines {
24 line_number - context_lines
25 } else {
26 1
27 };
28 let end_line = std::cmp::min(line_number + context_lines, lines.len());
29
30 let mut result = String::new();
31 for (i, line) in lines.iter().enumerate() {
32 let line_num = i + 1;
33 if line_num >= start_line && line_num <= end_line {
34 let marker = if line_num == line_number {
35 ">>>"
36 } else {
37 " "
38 };
39 result.push_str(&format!("{marker} {line_num:4}: {line}\n"));
40 }
41 }
42
43 Ok(result)
44 }
45
46 pub async fn find_and_display_definition(
47 &self,
48 symbol: &str,
49 path_filter: Option<&str>,
50 options: &SearchOptions,
51 ) -> Result<String> {
52 debug!("Finding potential definition locations...");
53 let file_locations = self
54 .find_symbol_locations(symbol, path_filter, options)
55 .await?;
56
57 if file_locations.is_empty() {
58 error!("No potential definitions found for '{symbol}'");
59 return Ok(String::new());
60 }
61
62 debug!(
63 "Found {} potential definition location(s)",
64 file_locations.len()
65 );
66
67 let is_ctor = symbol.rfind("::").is_some_and(|pos| {
68 let class_part = &symbol[..pos];
69 let method_part = &symbol[pos + 2..];
70 let class_name = class_part.split("::").last().unwrap_or(class_part);
71 class_name == method_part
72 });
73
74 let mut results = Vec::new();
75 for (file_path, line_number) in &file_locations {
76 let context_lines = if is_ctor { 2 } else { 10 };
77 match self
78 .get_definition_context(file_path, *line_number, context_lines)
79 .await
80 {
81 Ok(context) => {
82 if !context.is_empty() {
83 results.push(context);
84 }
85 }
86 Err(e) => {
87 error!("Could not fetch context: {e}");
88 }
89 }
90 }
91
92 if results.is_empty() {
93 error!("No definition found for symbol '{symbol}'");
94 Ok(String::new())
95 } else if results.len() == 1 {
96 Ok(results[0].clone())
97 } else {
98 Ok(results.join("\n\n"))
99 }
100 }
101}