pub mod examples;
pub mod python;
pub mod resolve;
pub mod triggers;
pub mod types;
pub use types::{ApiEntry, ApiKind, ApiSurface, Location, Param, Signature};
use crate::TldrResult;
pub fn extract_api_surface(
target: &str,
lang: Option<&str>,
include_private: bool,
limit: Option<usize>,
lookup: Option<&str>,
) -> TldrResult<ApiSurface> {
let resolved = resolve::resolve_target(target, lang)?;
let effective_lang = lang.unwrap_or("python");
let mut surface = match effective_lang {
"python" => python::extract_python_api_surface(&resolved, include_private, limit)?,
other => {
return Err(crate::error::TldrError::UnsupportedLanguage(format!(
"API surface extraction not yet supported for language: {}",
other
)))
}
};
if let Some(lookup_name) = lookup {
surface.apis.retain(|api| {
api.qualified_name == lookup_name
|| api.qualified_name.ends_with(&format!(".{}", lookup_name))
});
surface.total = surface.apis.len();
}
Ok(surface)
}
pub fn format_api_surface_text(surface: &ApiSurface) -> String {
let mut output = String::new();
output.push_str(&format!(
"API Surface: {} ({}) - {} APIs\n",
surface.package, surface.language, surface.total
));
output.push_str(&"=".repeat(60));
output.push('\n');
for api in &surface.apis {
output.push('\n');
output.push_str(&format!("[{}] {}\n", api.kind, api.qualified_name));
if let Some(sig) = &api.signature {
let params_str: Vec<String> = sig
.params
.iter()
.map(|p| {
let mut s = p.name.clone();
if p.is_variadic {
s = format!("*{}", s);
}
if p.is_keyword {
s = format!("**{}", s);
}
if let Some(t) = &p.type_annotation {
s = format!("{}: {}", s, t);
}
if let Some(d) = &p.default {
s = format!("{} = {}", s, d);
}
s
})
.collect();
let ret = sig
.return_type
.as_ref()
.map(|r| format!(" -> {}", r))
.unwrap_or_default();
let async_prefix = if sig.is_async { "async " } else { "" };
output.push_str(&format!(
" {}({}){}\n",
async_prefix,
params_str.join(", "),
ret
));
}
if let Some(doc) = &api.docstring {
output.push_str(&format!(" {}\n", doc));
}
if let Some(ex) = &api.example {
output.push_str(&format!(" Example: {}\n", ex));
}
if !api.triggers.is_empty() {
output.push_str(&format!(" Triggers: {}\n", api.triggers.join(", ")));
}
if let Some(loc) = &api.location {
output.push_str(&format!(" Location: {}:{}\n", loc.file.display(), loc.line));
}
}
output
}