use std::collections::HashMap;
use std::path::{Path, PathBuf};
use crate::error::{DbError, DiffError, ScanError};
use crate::model::{
Config, DepLevel, DepType, Dependency, File, ImpactEntry, ParseResult, ParseStatus, PathStep,
Symbol, SymbolKind, SymbolResult, SymbolWithParent, VcsFileChange,
};
pub trait ConfigStore {
fn config_get(&self, key: &str) -> Result<Option<String>, DbError>;
fn config_set(&self, key: &str, value: &str) -> Result<(), DbError>;
fn config_list(&self) -> Result<Vec<Config>, DbError>;
}
pub trait SymbolLookup {
fn get_file_id(&self, path: &str) -> Result<Option<i64>, DbError>;
fn get_symbol_by_id(&self, symbol_id: i64) -> Result<Option<Symbol>, DbError>;
fn search_symbols_by_name(&self, name: &str, limit: i64) -> Result<Vec<SymbolResult>, DbError>;
fn get_symbols_for_file(&self, file_id: i64) -> Result<Vec<Symbol>, DbError>;
fn get_children(&self, symbol_id: i64) -> Result<Vec<Symbol>, DbError>;
fn impact_analysis(&self, symbol_id: i64, max_depth: i64) -> Result<Vec<ImpactEntry>, DbError>;
fn stats(&self) -> Result<(i64, i64, i64), DbError>;
}
#[allow(clippy::too_many_arguments)]
pub trait ScanStore: ConfigStore + SymbolLookup {
fn begin_scan(&self) -> Result<i64, DbError>;
fn complete_scan(
&self,
scan_id: i64,
file_count: i64,
symbol_count: i64,
dep_count: i64,
) -> Result<(), DbError>;
fn upsert_file(
&self,
scan_id: i64,
path: &str,
language: &str,
size_bytes: i64,
content_hash: &str,
last_modified: u64,
parse_status: ParseStatus,
) -> Result<i64, DbError>;
fn get_file_hash(&self, path: &str) -> Result<Option<String>, DbError>;
fn get_all_file_paths(&self) -> Result<HashMap<String, i64>, DbError>;
fn delete_file(&self, file_id: i64) -> Result<(), DbError>;
fn insert_symbol(
&self,
file_id: i64,
parent_id: Option<i64>,
name: &str,
kind: SymbolKind,
signature: Option<&str>,
start_line: i64,
end_line: i64,
start_byte: i64,
end_byte: i64,
) -> Result<i64, DbError>;
fn delete_symbols_for_file(&self, file_id: i64) -> Result<(), DbError>;
fn insert_dependency(
&self,
source_file_id: i64,
source_symbol_id: Option<i64>,
target_file_id: Option<i64>,
target_symbol_id: Option<i64>,
dep_type: DepType,
level: DepLevel,
raw_import: Option<&str>,
) -> Result<i64, DbError>;
fn delete_deps_for_file(&self, file_id: i64) -> Result<(), DbError>;
}
pub trait QueryStore: ConfigStore + SymbolLookup {
fn search_symbols(&self, query: &str, limit: i64) -> Result<Vec<SymbolResult>, DbError>;
fn find_path(
&self,
from_symbol_id: i64,
to_symbol_id: i64,
max_depth: i64,
) -> Result<Vec<PathStep>, DbError>;
}
pub trait DiffStore: ConfigStore + SymbolLookup {
fn symbols_in_line_range(
&self,
file_path: &str,
start_line: i64,
end_line: i64,
) -> Result<Vec<SymbolResult>, DbError>;
fn all_symbols_for_file(&self, file_path: &str) -> Result<Vec<SymbolWithParent>, DbError>;
}
pub trait ExportStore: SymbolLookup {
fn list_files(&self, pattern: Option<&str>) -> Result<Vec<File>, DbError>;
fn get_deps_for_file(&self, file_id: i64) -> Result<Vec<Dependency>, DbError>;
}
pub trait VcsProvider {
fn working_tree_changes(&self, base_ref: Option<&str>)
-> Result<Vec<VcsFileChange>, DiffError>;
fn changes_between_refs(
&self,
from_ref: &str,
to_ref: &str,
) -> Result<Vec<VcsFileChange>, DiffError>;
fn read_file_at_ref(&self, path: &str, git_ref: &str) -> Result<Option<String>, DiffError>;
fn commit_count(&self, from_ref: &str, to_ref: &str) -> Result<usize, DiffError>;
fn resolve_ref(&self, refspec: &str) -> Result<bool, DiffError>;
fn head_sha(&self) -> Result<String, DiffError>;
fn root_commit_sha(&self) -> Result<Option<String>, DiffError>;
}
pub trait FileDiscovery: Send + Sync {
fn discover_files(
&self,
project_dir: &Path,
supported_ext: &[&str],
) -> Result<Vec<PathBuf>, ScanError>;
}
pub trait LanguageParser: Send + Sync {
fn parse(&self, source: &str, file_path: &Path) -> ParseResult;
fn language_name(&self) -> &str;
}
pub trait LanguageResolver: Send + Sync {
fn resolve_import(
&self,
import_path: &str,
source_file: &str,
project_root: &Path,
) -> Option<PathBuf>;
}
pub struct SiblingExpansion {
pub prefix: String,
pub extension: String,
pub root_only: bool,
}
pub trait LanguageRegistry: Send + Sync {
fn parser_for(&self, ext: &str) -> Option<&dyn LanguageParser>;
fn resolver_for(&self, ext: &str, root: &Path) -> Option<Box<dyn LanguageResolver>>;
fn supported_extensions(&self) -> &[&str];
fn config_files(&self) -> &[&str];
fn sibling_expansion(&self, rel_path: &str) -> Option<SiblingExpansion>;
}