searchfox_lib/
call_graph.rs1use crate::client::SearchfoxClient;
2use crate::types::SearchfoxResponse;
3use anyhow::Result;
4use reqwest::Url;
5use serde_json;
6
7pub struct CallGraphQuery {
8 pub calls_from: Option<String>,
9 pub calls_to: Option<String>,
10 pub calls_between: Option<(String, String)>,
11 pub depth: u32,
12}
13
14impl SearchfoxClient {
15 pub async fn search_call_graph(&self, query: &CallGraphQuery) -> Result<serde_json::Value> {
16 let query_string = if let Some(symbol) = &query.calls_from {
17 format!(
18 "calls-from:'{}' depth:{} graph-format:json",
19 symbol, query.depth
20 )
21 } else if let Some(symbol) = &query.calls_to {
22 format!(
23 "calls-to:'{}' depth:{} graph-format:json",
24 symbol, query.depth
25 )
26 } else if let Some((source, target)) = &query.calls_between {
27 format!(
28 "calls-between-source:'{}' calls-between-target:'{}' depth:{} graph-format:json",
29 source.trim(),
30 target.trim(),
31 query.depth
32 )
33 } else {
34 anyhow::bail!("No call graph query specified");
35 };
36
37 let mut url = Url::parse(&format!(
38 "https://searchfox.org/{}/query/default",
39 self.repo
40 ))?;
41 url.query_pairs_mut().append_pair("q", &query_string);
42
43 let response = self.get(url).await?;
44
45 if !response.status().is_success() {
46 anyhow::bail!("Request failed: {}", response.status());
47 }
48
49 let response_text = response.text().await?;
50
51 match serde_json::from_str::<serde_json::Value>(&response_text) {
52 Ok(json) => {
53 if let Some(symbol_graph) = json.get("SymbolGraphCollection") {
54 Ok(symbol_graph.clone())
55 } else {
56 match serde_json::from_str::<SearchfoxResponse>(&response_text) {
57 Ok(parsed_json) => {
58 let mut result = serde_json::json!({});
59 for (key, value) in &parsed_json {
60 if !key.starts_with('*')
61 && (value.as_array().is_some() || value.as_object().is_some())
62 {
63 result[key] = value.clone();
64 }
65 }
66 Ok(result)
67 }
68 Err(_) => Ok(json),
69 }
70 }
71 }
72 Err(_) => Ok(serde_json::json!({
73 "error": "Failed to parse response as JSON",
74 "raw_response": response_text
75 })),
76 }
77 }
78}