semantic/parser/
parser_core.rs1use std::sync::{Arc, OnceLock};
5
6use objects::object::ContentHash;
7use tree_sitter::{Node, Tree as TSTree};
8
9use super::{
10 parser_language::Language,
11 parser_pool::parse_fresh,
12 parser_types::{FunctionDef, Import},
13 syntax_index::{FunctionRef, ImportRef, SyntaxIndex},
14};
15
16#[derive(Debug)]
18pub struct ParsedFile {
19 pub language: Language,
20 pub source: Arc<str>,
21 content_hash: ContentHash,
22 tree: TSTree,
23 index: OnceLock<SyntaxIndex>,
24}
25
26impl ParsedFile {
27 pub fn parse(source: impl AsRef<str>, language: Language) -> Option<Self> {
29 let source = Arc::<str>::from(source.as_ref());
30 let content_hash = ContentHash::compute(source.as_bytes());
31 Self::parse_with_hash(source, language, content_hash)
32 }
33
34 pub fn parse_owned(source: String, language: Language) -> Option<Self> {
36 let content_hash = ContentHash::compute(source.as_bytes());
37 Self::parse_with_hash(Arc::<str>::from(source), language, content_hash)
38 }
39
40 pub(crate) fn parse_with_hash(
41 source: Arc<str>,
42 language: Language,
43 content_hash: ContentHash,
44 ) -> Option<Self> {
45 let tree = parse_fresh(source.as_bytes(), language)?;
46 if tree.root_node().has_error() {
47 return None;
48 }
49
50 Some(Self {
51 language,
52 source,
53 content_hash,
54 tree,
55 index: OnceLock::new(),
56 })
57 }
58
59 pub fn content_hash(&self) -> ContentHash {
61 self.content_hash
62 }
63
64 pub fn source(&self) -> &str {
66 &self.source
67 }
68
69 pub fn root_node(&self) -> Node<'_> {
71 self.tree.root_node()
72 }
73
74 pub fn syntax_index(&self) -> &SyntaxIndex {
76 self.index.get_or_init(|| {
77 SyntaxIndex::build(self.language, self.source.as_ref(), self.root_node())
78 })
79 }
80
81 pub fn functions(&self) -> impl Iterator<Item = FunctionRef<'_>> + '_ {
83 self.syntax_index().functions(self.source.as_ref())
84 }
85
86 pub fn imports(&self) -> impl Iterator<Item = ImportRef<'_>> + '_ {
88 self.syntax_index().imports(self.source.as_ref())
89 }
90
91 pub fn extract_functions(&self) -> Vec<FunctionDef> {
93 self.functions().map(FunctionRef::to_owned).collect()
94 }
95
96 pub fn extract_imports(&self) -> Vec<Import> {
98 self.imports().map(ImportRef::to_owned).collect()
99 }
100
101 pub fn is_function_kind(kind: &str, language: Language) -> bool {
103 super::syntax_index::is_function_kind(kind, language)
104 }
105}