use std::{fs, path::Path};
use masterror::AppError;
use super::ast_visitor::SemanticUnitVisitor;
use crate::{
error::{FileReadError, ParseError},
types::SemanticUnit,
};
pub fn extract_semantic_units(path: &Path) -> Result<Vec<SemanticUnit>, AppError> {
let content =
fs::read_to_string(path).map_err(|e| AppError::from(FileReadError::new(path, e)))?;
extract_semantic_units_from_str(&content, path)
}
pub fn extract_semantic_units_from_str(
content: &str,
path: &Path,
) -> Result<Vec<SemanticUnit>, AppError> {
let file = syn::parse_file(content)
.map_err(|e| AppError::from(ParseError::new(path, e.to_string())))?;
Ok(SemanticUnitVisitor::extract(&file))
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_extract_from_str() {
let code = r#"
pub fn main() {}
struct Config {}
impl Config {
pub fn new() -> Self { Config {} }
}
"#;
let units = extract_semantic_units_from_str(code, Path::new("test.rs"))
.expect("extraction should succeed");
assert!(units.len() >= 3);
}
#[test]
fn test_parse_error() {
let bad_code = "fn broken( {}";
let result = extract_semantic_units_from_str(bad_code, Path::new("bad.rs"));
assert!(result.is_err());
}
}