1use semtree_core::Language;
2use tree_sitter::{Node, Parser, Tree};
3
4use crate::ParseError;
5
6pub struct ParsedTree {
7 pub language: Language,
8 pub source: Vec<u8>,
9 pub tree: Tree,
10}
11
12impl ParsedTree {
13 pub fn root(&self) -> Node<'_> {
14 self.tree.root_node()
15 }
16
17 pub fn source_str(&self) -> &str {
18 std::str::from_utf8(&self.source).unwrap_or("")
19 }
20
21 pub fn node_text(&self, node: &Node<'_>) -> &str {
22 node.utf8_text(&self.source).unwrap_or("")
23 }
24}
25
26pub struct SemtreeParser;
27
28impl SemtreeParser {
29 pub fn parse(source: &str, language: Language) -> Result<ParsedTree, ParseError> {
30 let ts_language = ts_language(language)?;
31 let mut parser = Parser::new();
32 parser.set_language(&ts_language).expect("valid language");
33
34 let tree = parser.parse(source, None).ok_or(ParseError::ParseFailed)?;
35
36 Ok(ParsedTree {
37 language,
38 source: source.as_bytes().to_vec(),
39 tree,
40 })
41 }
42
43 pub fn parse_file(path: &std::path::Path) -> Result<ParsedTree, ParseError> {
44 let language = Language::from_path(path);
45 if language == Language::Unknown {
46 return Err(ParseError::UnsupportedLanguage(language));
47 }
48 let source = std::fs::read_to_string(path)?;
49 Self::parse(&source, language)
50 }
51}
52
53fn ts_language(lang: Language) -> Result<tree_sitter::Language, ParseError> {
54 match lang {
55 Language::Rust => Ok(tree_sitter_rust::LANGUAGE.into()),
56 Language::Python => Ok(tree_sitter_python::LANGUAGE.into()),
57 Language::JavaScript => Ok(tree_sitter_javascript::LANGUAGE.into()),
58 Language::TypeScript => Ok(tree_sitter_typescript::LANGUAGE_TYPESCRIPT.into()),
59 Language::Go => Ok(tree_sitter_go::LANGUAGE.into()),
60 Language::Unknown => Err(ParseError::UnsupportedLanguage(lang)),
61 }
62}