use dashmap::DashMap;
use lsp_types::{Location, Url};
use std::sync::{Arc, RwLock};
#[derive(Debug, Clone)]
pub struct SymbolInfo {
pub name: String,
pub symbol_type: SymbolType,
pub location: Location,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum SymbolType {
Struct,
Function,
Const,
Static,
Module,
}
#[derive(Debug, Clone)]
pub struct SymbolIndex {
pub symbols: DashMap<String, Vec<SymbolInfo>>,
}
impl SymbolIndex {
pub fn new() -> Self {
Self {
symbols: DashMap::new(),
}
}
pub fn add(&self, name: String, info: SymbolInfo) {
self.symbols.entry(name).or_default().push(info);
}
pub fn find(&self, name: &str) -> Vec<SymbolInfo> {
self.symbols
.get(name)
.map(|v| v.clone())
.unwrap_or_default()
}
pub fn clear(&self) {
self.symbols.clear();
}
}
impl Default for SymbolIndex {
fn default() -> Self {
Self::new()
}
}
#[derive(Debug, Clone)]
pub struct ComponentInfo {
pub name: String,
pub type_name: String,
pub location: Location,
pub plugin: Option<String>,
}
#[derive(Debug, Clone)]
pub struct ComponentIndex {
pub components: DashMap<String, ComponentInfo>,
}
impl ComponentIndex {
pub fn new() -> Self {
Self {
components: DashMap::new(),
}
}
pub fn add(&self, name: String, info: ComponentInfo) {
self.components.insert(name, info);
}
pub fn find(&self, name: &str) -> Option<ComponentInfo> {
self.components.get(name).map(|v| v.clone())
}
pub fn clear(&self) {
self.components.clear();
}
}
impl Default for ComponentIndex {
fn default() -> Self {
Self::new()
}
}
pub struct Workspace {
pub root_uri: Url,
pub documents: Vec<(Url, String)>,
}
pub struct IndexManager {
symbol_index: Arc<RwLock<SymbolIndex>>,
route_index: Arc<RwLock<crate::scanner::route::RouteIndex>>,
component_index: Arc<RwLock<ComponentIndex>>,
}
impl IndexManager {
pub fn new() -> Self {
Self {
symbol_index: Arc::new(RwLock::new(SymbolIndex::new())),
route_index: Arc::new(RwLock::new(crate::scanner::route::RouteIndex::new())),
component_index: Arc::new(RwLock::new(ComponentIndex::new())),
}
}
pub async fn build(&self, workspace: &Workspace) {
let symbol_index = self.symbol_index.clone();
let route_index = self.route_index.clone();
let component_index = self.component_index.clone();
let root_uri = workspace.root_uri.clone();
let documents = workspace.documents.clone();
tokio::spawn(async move {
let new_symbols = Self::build_symbol_index(&root_uri, &documents).await;
let new_routes = Self::build_route_index(&root_uri, &documents).await;
let new_components = Self::build_component_index(&root_uri, &documents).await;
*symbol_index
.write()
.expect("Failed to acquire write lock on symbol index") = new_symbols;
*route_index
.write()
.expect("Failed to acquire write lock on route index") = new_routes;
*component_index
.write()
.expect("Failed to acquire write lock on component index") = new_components;
tracing::info!("Index rebuild completed");
});
}
pub fn update(&self, uri: &Url, _content: &str) {
tracing::debug!("Updating index for {}", uri);
}
pub fn find_symbol(&self, name: &str) -> Vec<SymbolInfo> {
let index = self
.symbol_index
.read()
.expect("Failed to acquire read lock on symbol index");
index.find(name)
}
pub fn find_component(&self, name: &str) -> Option<ComponentInfo> {
let index = self
.component_index
.read()
.expect("Failed to acquire read lock on component index");
index.find(name)
}
pub fn get_all_routes(&self) -> Vec<crate::scanner::route::Route> {
let index = self
.route_index
.read()
.expect("Failed to acquire read lock on route index");
index.all_routes().into_iter().cloned().collect()
}
async fn build_symbol_index(_root_uri: &Url, _documents: &[(Url, String)]) -> SymbolIndex {
SymbolIndex::new()
}
async fn build_route_index(
_root_uri: &Url,
_documents: &[(Url, String)],
) -> crate::scanner::route::RouteIndex {
crate::scanner::route::RouteIndex::new()
}
async fn build_component_index(
_root_uri: &Url,
_documents: &[(Url, String)],
) -> ComponentIndex {
ComponentIndex::new()
}
}
impl Default for IndexManager {
fn default() -> Self {
Self::new()
}
}