#[cfg(feature = "rust")]
pub mod rust;
#[cfg(feature = "python")]
pub mod python;
#[cfg(feature = "typescript")]
pub mod typescript;
#[cfg(feature = "javascript")]
pub mod javascript;
#[cfg(feature = "go")]
pub mod go;
use crate::types::*;
pub fn extract_symbols(lang: Language, tree: &tree_sitter::Tree, source: &[u8]) -> (Vec<Symbol>, Vec<Import>) {
match lang {
#[cfg(feature = "rust")]
Language::Rust => rust::extract(tree, source),
#[cfg(feature = "python")]
Language::Python => python::extract(tree, source),
#[cfg(feature = "typescript")]
Language::TypeScript => typescript::extract(tree, source),
#[cfg(feature = "javascript")]
Language::JavaScript => javascript::extract(tree, source),
#[cfg(feature = "go")]
Language::Go => go::extract(tree, source),
#[allow(unreachable_patterns)]
_ => (Vec::new(), Vec::new()),
}
}
pub fn ts_language(lang: Language) -> Option<tree_sitter::Language> {
match lang {
#[cfg(feature = "rust")]
Language::Rust => Some(tree_sitter_rust::LANGUAGE.into()),
#[cfg(feature = "python")]
Language::Python => Some(tree_sitter_python::LANGUAGE.into()),
#[cfg(feature = "typescript")]
Language::TypeScript => Some(tree_sitter_typescript::LANGUAGE_TSX.into()),
#[cfg(feature = "javascript")]
Language::JavaScript => Some(tree_sitter_javascript::LANGUAGE.into()),
#[cfg(feature = "go")]
Language::Go => Some(tree_sitter_go::LANGUAGE.into()),
#[allow(unreachable_patterns)]
_ => None,
}
}
pub(crate) fn node_text<'a>(node: &tree_sitter::Node, source: &'a [u8]) -> &'a str {
node.utf8_text(source).unwrap_or("")
}
pub(crate) fn field_text<'a>(node: &tree_sitter::Node, field: &str, source: &'a [u8]) -> Option<&'a str> {
node.child_by_field_name(field).map(|n| node_text(&n, source))
}
pub(crate) fn extract_doc_comment(node: &tree_sitter::Node, source: &[u8]) -> Option<String> {
let mut comments = Vec::new();
let mut sibling = node.prev_sibling();
while let Some(s) = sibling {
let kind = s.kind();
if kind == "line_comment" || kind == "comment" || kind == "block_comment" {
let text = node_text(&s, source);
if text.starts_with("///") || text.starts_with("/**") || text.starts_with("## ") {
comments.push(text.to_string());
} else {
break;
}
} else if kind == "attribute_item" || kind == "decorator" {
} else {
break;
}
sibling = s.prev_sibling();
}
if comments.is_empty() {
None
} else {
comments.reverse();
Some(comments.join("\n"))
}
}
pub(crate) fn extract_signature(node: &tree_sitter::Node, body_field: &str, source: &[u8]) -> String {
if let Some(body) = node.child_by_field_name(body_field) {
let sig_end = body.start_byte();
let sig = &source[node.start_byte()..sig_end];
std::str::from_utf8(sig).unwrap_or("").trim().to_string()
} else {
node_text(node, source).to_string()
}
}