use crate::{
cancelation::Canceled, change::AnalysisChange, completion, db::AnalysisDatabase, diagnostics,
diagnostics::Diagnostic, file_structure, FilePosition,
};
use mun_hir::{line_index::LineIndex, AstDatabase, SourceDatabase};
use mun_syntax::SourceFile;
use salsa::{ParallelDatabase, Snapshot};
use std::sync::Arc;
pub type Cancelable<T> = Result<T, Canceled>;
#[derive(Default)]
pub struct Analysis {
db: AnalysisDatabase,
}
impl Analysis {
pub fn apply_change(&mut self, change: AnalysisChange) {
self.db.apply_change(change)
}
pub fn snapshot(&self) -> AnalysisSnapshot {
AnalysisSnapshot {
db: self.db.snapshot(),
}
}
pub fn request_cancelation(&mut self) {
self.db.request_cancelation();
}
}
pub struct AnalysisSnapshot {
db: Snapshot<AnalysisDatabase>,
}
impl AnalysisSnapshot {
pub fn parse(&self, file_id: mun_hir::FileId) -> Cancelable<SourceFile> {
self.with_db(|db| db.parse(file_id).tree())
}
pub fn diagnostics(&self, file_id: mun_hir::FileId) -> Cancelable<Vec<Diagnostic>> {
self.with_db(|db| diagnostics::diagnostics(db, file_id))
}
pub fn package_source_files(
&self,
package_id: mun_hir::PackageId,
) -> Cancelable<Vec<mun_hir::FileId>> {
self.with_db(|db| {
let packages = db.packages();
let source_root = db.source_root(packages[package_id].source_root);
source_root.files().collect()
})
}
pub fn file_line_index(&self, file_id: mun_hir::FileId) -> Cancelable<Arc<LineIndex>> {
self.with_db(|db| db.line_index(file_id))
}
pub fn file_structure(
&self,
file_id: mun_hir::FileId,
) -> Cancelable<Vec<file_structure::StructureNode>> {
self.with_db(|db| file_structure::file_structure(&db.parse(file_id).tree()))
}
pub fn completions(
&self,
position: FilePosition,
) -> Cancelable<Option<Vec<completion::CompletionItem>>> {
self.with_db(|db| completion::completions(db, position).map(Into::into))
}
fn with_db<F: FnOnce(&AnalysisDatabase) -> T + std::panic::UnwindSafe, T>(
&self,
f: F,
) -> Cancelable<T> {
self.db.catch_canceled(f)
}
}