From d8aee31a600a8a8a56ddee0ee2ff1c5d5ba2320b Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sun, 7 Oct 2018 13:18:25 +0300 Subject: start salsa migration --- crates/ra_analysis/src/db/mod.rs | 226 ++++++++++++++++++++++++--------- crates/ra_analysis/src/lib.rs | 4 +- crates/ra_analysis/src/roots.rs | 68 ++++++---- crates/ra_analysis/src/symbol_index.rs | 9 ++ 4 files changed, 218 insertions(+), 89 deletions(-) (limited to 'crates/ra_analysis/src') diff --git a/crates/ra_analysis/src/db/mod.rs b/crates/ra_analysis/src/db/mod.rs index 4eb7d922d..4b3e0fc90 100644 --- a/crates/ra_analysis/src/db/mod.rs +++ b/crates/ra_analysis/src/db/mod.rs @@ -1,85 +1,193 @@ -mod imp; - use std::{ + fmt, sync::Arc, + hash::{Hash, Hasher}, + collections::HashSet, }; -use im; use salsa; -use crate::{FileId, imp::FileResolverImp}; +use ra_syntax::File; +use ra_editor::{LineIndex}; +use crate::{ + symbol_index::SymbolIndex, + FileId, FileResolverImp +}; -#[derive(Debug, Default, Clone)] -pub(crate) struct State { - pub(crate) file_map: im::HashMap>, - pub(crate) file_resolver: FileResolverImp +#[derive(Default)] +pub(crate) struct RootDatabase { + runtime: salsa::runtime::Runtime, } -#[derive(Debug)] -pub(crate) struct Db { - imp: imp::Db, +impl fmt::Debug for RootDatabase { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + fmt.write_str("RootDatabase { ... }") + } } -#[derive(Clone, Copy)] -pub(crate) struct QueryCtx<'a> { - imp: &'a salsa::QueryCtx, +impl salsa::Database for RootDatabase { + fn salsa_runtime(&self) -> &salsa::runtime::Runtime { + &self.runtime + } } -pub(crate) struct Query(pub(crate) u16, pub(crate) fn(QueryCtx, &T) -> R); - -pub(crate) struct QueryRegistry { - imp: imp::QueryRegistry, +salsa::database_storage! { + pub(crate) struct RootDatabaseStorage for RootDatabase { + impl FilesDatabase { + fn file_text() for FileTextQuery; + fn file_set() for FileSetQuery; + } + impl SyntaxDatabase { + fn file_syntax() for FileSyntaxQuery; + fn file_lines() for FileLinesQuery; + fn file_symbols() for FileSymbolsQuery; + } + } } -impl Default for Db { - fn default() -> Db { - Db::new() +salsa::query_group! { + pub(crate) trait FilesDatabase: salsa::Database { + fn file_text(file_id: FileId) -> Arc { + type FileTextQuery; + storage input; + } + fn file_set(key: ()) -> Arc { + type FileSetQuery; + storage input; + } } } -impl Db { - pub(crate) fn new() -> Db { - let reg = QueryRegistry::new(); - Db { imp: imp::Db::new(reg.imp) } - } - pub(crate) fn state(&self) -> &State { - self.imp.imp.ground_data() - } - pub(crate) fn with_changes(&self, new_state: State, changed_files: &[FileId], resolver_changed: bool) -> Db { - Db { imp: self.imp.with_changes(new_state, changed_files, resolver_changed) } - } - pub(crate) fn make_query R, R>(&self, f: F) -> R { - let ctx = QueryCtx { imp: &self.imp.imp.query_ctx() }; - f(ctx) - } - #[allow(unused)] - pub(crate) fn trace_query R, R>(&self, f: F) -> (R, Vec<&'static str>) { - let ctx = QueryCtx { imp: &self.imp.imp.query_ctx() }; - let res = f(ctx); - let trace = self.imp.extract_trace(ctx.imp); - (res, trace) - } +#[derive(Default, Debug)] +pub(crate) struct FileSet { + pub(crate) files: HashSet, + pub(crate) resolver: FileResolverImp, } -impl<'a> QueryCtx<'a> { - pub(crate) fn get(&self, q: Q, params: Q::Params) -> Arc { - q.get(self, params) +impl PartialEq for FileSet { + fn eq(&self, other: &FileSet) -> bool { + self.files == other.files } } -pub(crate) fn file_text(ctx: QueryCtx, file_id: FileId) -> Arc { - imp::file_text(ctx, file_id) +impl Eq for FileSet { } -pub(crate) fn file_set(ctx: QueryCtx) -> Arc<(Vec, FileResolverImp)> { - imp::file_set(ctx) -} -impl QueryRegistry { - fn new() -> QueryRegistry { - let mut reg = QueryRegistry { imp: imp::QueryRegistry::new() }; - crate::queries::register_queries(&mut reg); - crate::module_map::register_queries(&mut reg); - reg +impl Hash for FileSet { + fn hash(&self, hasher: &mut H) { + let mut files = self.files.iter().cloned().collect::>(); + files.sort(); + files.hash(hasher); } - pub(crate) fn add(&mut self, q: Q, name: &'static str) { - self.imp.add(q, name) +} + +salsa::query_group! { + pub(crate) trait SyntaxDatabase: FilesDatabase { + fn file_syntax(file_id: FileId) -> File { + type FileSyntaxQuery; + } + fn file_lines(file_id: FileId) -> Arc { + type FileLinesQuery; + } + fn file_symbols(file_id: FileId) -> Arc { + type FileSymbolsQuery; + } } } + +fn file_syntax(db: &impl SyntaxDatabase, file_id: FileId) -> File { + let text = db.file_text(file_id); + File::parse(&*text) +} +fn file_lines(db: &impl SyntaxDatabase, file_id: FileId) -> Arc { + let text = db.file_text(file_id); + Arc::new(LineIndex::new(&*text)) +} +fn file_symbols(db: &impl SyntaxDatabase, file_id: FileId) -> Arc { + let syntax = db.file_syntax(file_id); + Arc::new(SymbolIndex::for_file(file_id, syntax)) +} + +// mod imp; + +// use std::{ +// sync::Arc, +// }; +// use im; +// use salsa; +// use {FileId, imp::FileResolverImp}; + +// #[derive(Debug, Default, Clone)] +// pub(crate) struct State { +// pub(crate) file_map: im::HashMap>, +// pub(crate) file_resolver: FileResolverImp +// } + +// #[derive(Debug)] +// pub(crate) struct Db { +// imp: imp::Db, +// } + +// #[derive(Clone, Copy)] +// pub(crate) struct QueryCtx<'a> { +// imp: &'a salsa::QueryCtx, +// } + +// pub(crate) struct Query(pub(crate) u16, pub(crate) fn(QueryCtx, &T) -> R); + +// pub(crate) struct QueryRegistry { +// imp: imp::QueryRegistry, +// } + +// impl Default for Db { +// fn default() -> Db { +// Db::new() +// } +// } + +// impl Db { +// pub(crate) fn new() -> Db { +// let reg = QueryRegistry::new(); +// Db { imp: imp::Db::new(reg.imp) } +// } +// pub(crate) fn state(&self) -> &State { +// self.imp.imp.ground_data() +// } +// pub(crate) fn with_changes(&self, new_state: State, changed_files: &[FileId], resolver_changed: bool) -> Db { +// Db { imp: self.imp.with_changes(new_state, changed_files, resolver_changed) } +// } +// pub(crate) fn make_query R, R>(&self, f: F) -> R { +// let ctx = QueryCtx { imp: &self.imp.imp.query_ctx() }; +// f(ctx) +// } +// #[allow(unused)] +// pub(crate) fn trace_query R, R>(&self, f: F) -> (R, Vec<&'static str>) { +// let ctx = QueryCtx { imp: &self.imp.imp.query_ctx() }; +// let res = f(ctx); +// let trace = self.imp.extract_trace(ctx.imp); +// (res, trace) +// } +// } + +// impl<'a> QueryCtx<'a> { +// pub(crate) fn get(&self, q: Q, params: Q::Params) -> Arc { +// q.get(self, params) +// } +// } + +// pub(crate) fn file_text(ctx: QueryCtx, file_id: FileId) -> Arc { +// imp::file_text(ctx, file_id) +// } + +// pub(crate) fn file_set(ctx: QueryCtx) -> Arc<(Vec, FileResolverImp)> { +// imp::file_set(ctx) +// } +// impl QueryRegistry { +// fn new() -> QueryRegistry { +// let mut reg = QueryRegistry { imp: imp::QueryRegistry::new() }; +// ::queries::register_queries(&mut reg); +// ::module_map::register_queries(&mut reg); +// reg +// } +// pub(crate) fn add(&mut self, q: Q, name: &'static str) { +// self.imp.add(q, name) +// } +// } diff --git a/crates/ra_analysis/src/lib.rs b/crates/ra_analysis/src/lib.rs index 86c66236c..4c1ccdeaf 100644 --- a/crates/ra_analysis/src/lib.rs +++ b/crates/ra_analysis/src/lib.rs @@ -14,12 +14,12 @@ extern crate salsa; extern crate rustc_hash; mod symbol_index; -mod module_map; +// mod module_map; mod imp; mod job; mod roots; mod db; -mod queries; +// mod queries; mod descriptors; use std::{ diff --git a/crates/ra_analysis/src/roots.rs b/crates/ra_analysis/src/roots.rs index 208acc4c2..7a7d1169e 100644 --- a/crates/ra_analysis/src/roots.rs +++ b/crates/ra_analysis/src/roots.rs @@ -1,11 +1,13 @@ use std::{ + collections::{HashMap, HashSet}, sync::Arc, panic, }; +use parking_lot::RwLock; use once_cell::sync::OnceCell; use rayon::prelude::*; -use rustc_hash::FxHashMap; +use salsa::Database; use ra_editor::LineIndex; use ra_syntax::File; @@ -14,7 +16,7 @@ use crate::{ imp::FileResolverImp, symbol_index::SymbolIndex, descriptors::{ModuleDescriptor, ModuleTreeDescriptor}, - db::Db, + db::{self, FilesDatabase, SyntaxDatabase} }; pub(crate) trait SourceRoot { @@ -25,9 +27,9 @@ pub(crate) trait SourceRoot { fn symbols(&self, acc: &mut Vec>); } -#[derive(Default, Debug)] +#[derive(Default, Debug, Clone)] pub(crate) struct WritableSourceRoot { - db: Db, + db: Arc>, } impl WritableSourceRoot { @@ -36,51 +38,61 @@ impl WritableSourceRoot { changes: &mut dyn Iterator)>, file_resolver: Option, ) -> WritableSourceRoot { - let resolver_changed = file_resolver.is_some(); - let mut changed_files = Vec::new(); - let mut new_state = self.db.state().clone(); - + let db = self.db.write(); + let mut changed = HashSet::new(); + let mut removed = HashSet::new(); for (file_id, text) in changes { - changed_files.push(file_id); match text { - Some(text) => { - new_state.file_map.insert(file_id, Arc::new(text)); - }, None => { - new_state.file_map.remove(&file_id); + removed.insert(file_id); + } + Some(text) => { + db.query(db::FileTextQuery) + .set(file_id, Arc::new(text)); + changed.insert(file_id); } } } - if let Some(file_resolver) = file_resolver { - new_state.file_resolver = file_resolver - } - WritableSourceRoot { - db: self.db.with_changes(new_state, &changed_files, resolver_changed) + if let Some(resolver) = file_resolver { + let mut files: HashSet = db.file_set(()) + .files + .clone(); + for file_id in removed { + files.remove(&file_id); + } + files.extend(changed); + db.query(db::FileSetQuery) + .set((), Arc::new(db::FileSet { files, resolver })) } + // TODO: reconcile sasla's API with our needs + // https://github.com/salsa-rs/salsa/issues/12 + self.clone() } } impl SourceRoot for WritableSourceRoot { fn module_tree(&self) -> Arc { - self.db.make_query(crate::module_map::module_tree) + unimplemented!() + //self.db.make_query(::module_map::module_tree) } fn contains(&self, file_id: FileId) -> bool { - self.db.state().file_map.contains_key(&file_id) + self.db.read().file_set(()).files.contains(&file_id) } fn lines(&self, file_id: FileId) -> Arc { - self.db.make_query(|ctx| crate::queries::file_lines(ctx, file_id)) + self.db.read().file_lines(file_id) } fn syntax(&self, file_id: FileId) -> File { - self.db.make_query(|ctx| crate::queries::file_syntax(ctx, file_id)) + self.db.read().file_syntax(file_id) } fn symbols<'a>(&'a self, acc: &mut Vec>) { - self.db.make_query(|ctx| { - let file_set = crate::queries::file_set(ctx); - let syms = file_set.0.iter() - .map(|file_id| crate::queries::file_symbols(ctx, *file_id)); - acc.extend(syms); - }); + let db = self.db.read(); + let symbols = db.file_set(()); + let symbols = symbols + .files + .iter() + .map(|&file_id| db.file_symbols(file_id)); + acc.extend(symbols); } } diff --git a/crates/ra_analysis/src/symbol_index.rs b/crates/ra_analysis/src/symbol_index.rs index e5d83d365..54672fde4 100644 --- a/crates/ra_analysis/src/symbol_index.rs +++ b/crates/ra_analysis/src/symbol_index.rs @@ -17,6 +17,15 @@ pub(crate) struct SymbolIndex { map: fst::Map, } +impl PartialEq for SymbolIndex { + fn eq(&self, other: &SymbolIndex) -> bool { + self.symbols == other.symbols + } +} + +impl Eq for SymbolIndex { +} + impl Hash for SymbolIndex { fn hash(&self, hasher: &mut H) { self.symbols.hash(hasher) -- cgit v1.2.3