use std::sync::Arc;
use harn_vm::VmValue;
use crate::error::HostlibError;
use crate::registry::{BuiltinRegistry, HostlibCapability, RegisteredBuiltin, SyncHandler};
mod language;
mod outline;
mod parse;
mod symbols;
mod symbols_call;
mod types;
pub use language::Language;
pub use types::{OutlineItem, ParsedNode, Symbol, SymbolKind};
pub mod api {
use std::path::Path;
use crate::error::HostlibError;
use super::language::Language;
use super::outline::build_outline;
use super::parse::{parse_source, read_source};
use super::symbols::extract;
use super::types::{OutlineItem, Symbol};
pub fn symbols(
path: &Path,
language_hint: Option<&str>,
) -> Result<(Language, Vec<Symbol>), HostlibError> {
let language = detect(path, language_hint)?;
let source = read_source(&path.to_string_lossy(), 0)?;
let tree = parse_source(&source, language)?;
Ok((language, extract(&tree, &source, language)))
}
pub fn outline(
path: &Path,
language_hint: Option<&str>,
) -> Result<(Language, Vec<OutlineItem>), HostlibError> {
let (language, symbols) = symbols(path, language_hint)?;
Ok((language, build_outline(symbols)))
}
pub fn symbols_from_source(
source: &str,
language: Language,
) -> Result<Vec<Symbol>, HostlibError> {
let tree = parse_source(source, language)?;
Ok(extract(&tree, source, language))
}
fn detect(path: &Path, language_hint: Option<&str>) -> Result<Language, HostlibError> {
Language::detect(path, language_hint).ok_or_else(|| HostlibError::InvalidParameter {
builtin: "ast::api",
param: "language",
message: format!(
"could not infer a tree-sitter grammar for `{}` \
(extension or `language` field unrecognized)",
path.display()
),
})
}
}
#[derive(Default)]
pub struct AstCapability;
impl HostlibCapability for AstCapability {
fn module_name(&self) -> &'static str {
"ast"
}
fn register_builtins(&self, registry: &mut BuiltinRegistry) {
register(registry, "hostlib_ast_parse_file", "parse_file", parse::run);
register(
registry,
"hostlib_ast_symbols",
"symbols",
symbols_call::run,
);
register(registry, "hostlib_ast_outline", "outline", outline::run);
}
}
fn register(
registry: &mut BuiltinRegistry,
name: &'static str,
method: &'static str,
runner: fn(&[VmValue]) -> Result<VmValue, HostlibError>,
) {
let handler: SyncHandler = Arc::new(runner);
registry.register(RegisteredBuiltin {
name,
module: "ast",
method,
handler,
});
}