1use std::sync::Arc;
31
32use harn_vm::VmValue;
33
34use crate::error::HostlibError;
35use crate::registry::{BuiltinRegistry, HostlibCapability, RegisteredBuiltin, SyncHandler};
36
37mod language;
38mod outline;
39mod parse;
40mod symbols;
41mod symbols_call;
42mod types;
43
44pub use language::Language;
45pub use types::{OutlineItem, ParsedNode, Symbol, SymbolKind};
46
47pub mod api {
51 use std::path::Path;
52
53 use crate::error::HostlibError;
54
55 use super::language::Language;
56 use super::outline::build_outline;
57 use super::parse::{parse_source, read_source};
58 use super::symbols::extract;
59 use super::types::{OutlineItem, Symbol};
60
61 pub fn symbols(
63 path: &Path,
64 language_hint: Option<&str>,
65 ) -> Result<(Language, Vec<Symbol>), HostlibError> {
66 let language = detect(path, language_hint)?;
67 let source = read_source(&path.to_string_lossy(), 0)?;
68 let tree = parse_source(&source, language)?;
69 Ok((language, extract(&tree, &source, language)))
70 }
71
72 pub fn outline(
74 path: &Path,
75 language_hint: Option<&str>,
76 ) -> Result<(Language, Vec<OutlineItem>), HostlibError> {
77 let (language, symbols) = symbols(path, language_hint)?;
78 Ok((language, build_outline(symbols)))
79 }
80
81 pub fn symbols_from_source(
84 source: &str,
85 language: Language,
86 ) -> Result<Vec<Symbol>, HostlibError> {
87 let tree = parse_source(source, language)?;
88 Ok(extract(&tree, source, language))
89 }
90
91 fn detect(path: &Path, language_hint: Option<&str>) -> Result<Language, HostlibError> {
92 Language::detect(path, language_hint).ok_or_else(|| HostlibError::InvalidParameter {
93 builtin: "ast::api",
94 param: "language",
95 message: format!(
96 "could not infer a tree-sitter grammar for `{}` \
97 (extension or `language` field unrecognized)",
98 path.display()
99 ),
100 })
101 }
102}
103
104#[derive(Default)]
108pub struct AstCapability;
109
110impl HostlibCapability for AstCapability {
111 fn module_name(&self) -> &'static str {
112 "ast"
113 }
114
115 fn register_builtins(&self, registry: &mut BuiltinRegistry) {
116 register(registry, "hostlib_ast_parse_file", "parse_file", parse::run);
117 register(
118 registry,
119 "hostlib_ast_symbols",
120 "symbols",
121 symbols_call::run,
122 );
123 register(registry, "hostlib_ast_outline", "outline", outline::run);
124 }
125}
126
127fn register(
128 registry: &mut BuiltinRegistry,
129 name: &'static str,
130 method: &'static str,
131 runner: fn(&[VmValue]) -> Result<VmValue, HostlibError>,
132) {
133 let handler: SyncHandler = Arc::new(runner);
134 registry.register(RegisteredBuiltin {
135 name,
136 module: "ast",
137 method,
138 handler,
139 });
140}