use tree_sitter::{Node, Parser, Tree};
use super::base::{get_node_text, walk_tree};
use super::ParseError;
use crate::callgraph::cross_file_types::ImportDef;
pub(crate) fn parse_include(node: &Node, source: &[u8]) -> Option<ImportDef> {
for i in 0..node.child_count() {
if let Some(child) = node.child(i) {
match child.kind() {
"string_literal" => {
let text = get_node_text(&child, source);
let module = text.trim_matches('"').to_string();
let mut imp = ImportDef::simple_import(module);
imp.is_namespace = false; return Some(imp);
}
"system_lib_string" => {
let text = get_node_text(&child, source);
let module = text.trim_matches(|c| c == '<' || c == '>').to_string();
let mut imp = ImportDef::simple_import(module);
imp.is_namespace = true; return Some(imp);
}
_ => {}
}
}
}
None
}
pub(crate) fn parse_preproc_imports(tree: &Tree, source: &str) -> Vec<ImportDef> {
let source_bytes = source.as_bytes();
let mut imports = Vec::new();
for node in walk_tree(tree.root_node()) {
if node.kind() == "preproc_include" {
if let Some(imp) = parse_include(&node, source_bytes) {
imports.push(imp);
}
}
}
imports
}
pub(crate) fn parse_source_with_language(
source: &str,
ts_language: tree_sitter::Language,
lang_name: &str,
) -> Result<Tree, ParseError> {
let mut parser = Parser::new();
parser
.set_language(&ts_language)
.map_err(|e| ParseError::ParseFailed {
file: std::path::PathBuf::new(),
message: format!("Failed to set {} language: {}", lang_name, e),
})?;
parser
.parse(source, None)
.ok_or_else(|| ParseError::ParseFailed {
file: std::path::PathBuf::new(),
message: "Parser returned None".to_string(),
})
}