Skip to main content

aft/
language.rs

1use std::path::Path;
2
3use crate::error::AftError;
4pub use crate::symbols::{Range, Symbol, SymbolMatch};
5
6/// An explicitly declared heading anchor used as a URL fragment, with its source location.
7#[derive(Debug, Clone, PartialEq, Eq)]
8pub struct HeadingAnchor {
9    pub start_line: u32,
10    pub start_col: u32,
11    pub id: String,
12}
13
14/// Trait for language-specific symbol resolution.
15///
16/// S02 implements this with tree-sitter parsing via `TreeSitterProvider`.
17pub trait LanguageProvider: Send + Sync {
18    /// Resolve a symbol by name within a file. Returns all matches.
19    fn resolve_symbol(&self, file: &Path, name: &str) -> Result<Vec<SymbolMatch>, AftError>;
20
21    /// List all top-level symbols in a file.
22    fn list_symbols(&self, file: &Path) -> Result<Vec<Symbol>, AftError>;
23
24    /// Return explicitly declared heading anchors and their source locations.
25    fn heading_anchors(&self, _file: &Path) -> Result<Vec<HeadingAnchor>, AftError> {
26        Ok(Vec::new())
27    }
28
29    /// Downcast to concrete type for provider-specific operations.
30    fn as_any(&self) -> &dyn std::any::Any;
31}
32
33/// Placeholder provider that rejects all calls.
34///
35/// Retained for tests and fallback. Production code uses `TreeSitterProvider`.
36pub struct StubProvider;
37
38impl LanguageProvider for StubProvider {
39    fn resolve_symbol(&self, _file: &Path, _name: &str) -> Result<Vec<SymbolMatch>, AftError> {
40        Err(AftError::InvalidRequest {
41            message: "no language provider configured".to_string(),
42        })
43    }
44
45    fn list_symbols(&self, _file: &Path) -> Result<Vec<Symbol>, AftError> {
46        Err(AftError::InvalidRequest {
47            message: "no language provider configured".to_string(),
48        })
49    }
50
51    fn as_any(&self) -> &dyn std::any::Any {
52        self
53    }
54}