aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock8
-rw-r--r--crates/ra_analysis/src/db/mod.rs226
-rw-r--r--crates/ra_analysis/src/lib.rs4
-rw-r--r--crates/ra_analysis/src/roots.rs68
-rw-r--r--crates/ra_analysis/src/symbol_index.rs9
-rw-r--r--crates/ra_editor/src/line_index.rs2
-rw-r--r--crates/ra_editor/src/symbols.rs2
-rw-r--r--crates/ra_syntax/src/lib.rs2
8 files changed, 221 insertions, 100 deletions
diff --git a/Cargo.lock b/Cargo.lock
index b9b430262..98f06f53a 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -844,14 +844,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
844 844
845[[package]] 845[[package]]
846name = "salsa" 846name = "salsa"
847version = "0.1.0"
848dependencies = [
849 "im 12.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
850 "parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)",
851]
852
853[[package]]
854name = "salsa"
855version = "0.4.1" 847version = "0.4.1"
856source = "registry+https://github.com/rust-lang/crates.io-index" 848source = "registry+https://github.com/rust-lang/crates.io-index"
857dependencies = [ 849dependencies = [
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 @@
1mod imp;
2
3use std::{ 1use std::{
2 fmt,
4 sync::Arc, 3 sync::Arc,
4 hash::{Hash, Hasher},
5 collections::HashSet,
5}; 6};
6use im;
7use salsa; 7use salsa;
8use crate::{FileId, imp::FileResolverImp}; 8use ra_syntax::File;
9use ra_editor::{LineIndex};
10use crate::{
11 symbol_index::SymbolIndex,
12 FileId, FileResolverImp
13};
9 14
10#[derive(Debug, Default, Clone)] 15#[derive(Default)]
11pub(crate) struct State { 16pub(crate) struct RootDatabase {
12 pub(crate) file_map: im::HashMap<FileId, Arc<String>>, 17 runtime: salsa::runtime::Runtime<RootDatabase>,
13 pub(crate) file_resolver: FileResolverImp
14} 18}
15 19
16#[derive(Debug)] 20impl fmt::Debug for RootDatabase {
17pub(crate) struct Db { 21 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
18 imp: imp::Db, 22 fmt.write_str("RootDatabase { ... }")
23 }
19} 24}
20 25
21#[derive(Clone, Copy)] 26impl salsa::Database for RootDatabase {
22pub(crate) struct QueryCtx<'a> { 27 fn salsa_runtime(&self) -> &salsa::runtime::Runtime<RootDatabase> {
23 imp: &'a salsa::QueryCtx<State, imp::Data>, 28 &self.runtime
29 }
24} 30}
25 31
26pub(crate) struct Query<T, R>(pub(crate) u16, pub(crate) fn(QueryCtx, &T) -> R); 32salsa::database_storage! {
27 33 pub(crate) struct RootDatabaseStorage for RootDatabase {
28pub(crate) struct QueryRegistry { 34 impl FilesDatabase {
29 imp: imp::QueryRegistry, 35 fn file_text() for FileTextQuery;
36 fn file_set() for FileSetQuery;
37 }
38 impl SyntaxDatabase {
39 fn file_syntax() for FileSyntaxQuery;
40 fn file_lines() for FileLinesQuery;
41 fn file_symbols() for FileSymbolsQuery;
42 }
43 }
30} 44}
31 45
32impl Default for Db { 46salsa::query_group! {
33 fn default() -> Db { 47 pub(crate) trait FilesDatabase: salsa::Database {
34 Db::new() 48 fn file_text(file_id: FileId) -> Arc<String> {
49 type FileTextQuery;
50 storage input;
51 }
52 fn file_set(key: ()) -> Arc<FileSet> {
53 type FileSetQuery;
54 storage input;
55 }
35 } 56 }
36} 57}
37 58
38impl Db { 59#[derive(Default, Debug)]
39 pub(crate) fn new() -> Db { 60pub(crate) struct FileSet {
40 let reg = QueryRegistry::new(); 61 pub(crate) files: HashSet<FileId>,
41 Db { imp: imp::Db::new(reg.imp) } 62 pub(crate) resolver: FileResolverImp,
42 }
43 pub(crate) fn state(&self) -> &State {
44 self.imp.imp.ground_data()
45 }
46 pub(crate) fn with_changes(&self, new_state: State, changed_files: &[FileId], resolver_changed: bool) -> Db {
47 Db { imp: self.imp.with_changes(new_state, changed_files, resolver_changed) }
48 }
49 pub(crate) fn make_query<F: FnOnce(QueryCtx) -> R, R>(&self, f: F) -> R {
50 let ctx = QueryCtx { imp: &self.imp.imp.query_ctx() };
51 f(ctx)
52 }
53 #[allow(unused)]
54 pub(crate) fn trace_query<F: FnOnce(QueryCtx) -> R, R>(&self, f: F) -> (R, Vec<&'static str>) {
55 let ctx = QueryCtx { imp: &self.imp.imp.query_ctx() };
56 let res = f(ctx);
57 let trace = self.imp.extract_trace(ctx.imp);
58 (res, trace)
59 }
60} 63}
61 64
62impl<'a> QueryCtx<'a> { 65impl PartialEq for FileSet {
63 pub(crate) fn get<Q: imp::EvalQuery>(&self, q: Q, params: Q::Params) -> Arc<Q::Output> { 66 fn eq(&self, other: &FileSet) -> bool {
64 q.get(self, params) 67 self.files == other.files
65 } 68 }
66} 69}
67 70
68pub(crate) fn file_text(ctx: QueryCtx, file_id: FileId) -> Arc<String> { 71impl Eq for FileSet {
69 imp::file_text(ctx, file_id)
70} 72}
71 73
72pub(crate) fn file_set(ctx: QueryCtx) -> Arc<(Vec<FileId>, FileResolverImp)> { 74impl Hash for FileSet {
73 imp::file_set(ctx) 75 fn hash<H: Hasher>(&self, hasher: &mut H) {
74} 76 let mut files = self.files.iter().cloned().collect::<Vec<_>>();
75impl QueryRegistry { 77 files.sort();
76 fn new() -> QueryRegistry { 78 files.hash(hasher);
77 let mut reg = QueryRegistry { imp: imp::QueryRegistry::new() };
78 crate::queries::register_queries(&mut reg);
79 crate::module_map::register_queries(&mut reg);
80 reg
81 } 79 }
82 pub(crate) fn add<Q: imp::EvalQuery>(&mut self, q: Q, name: &'static str) { 80}
83 self.imp.add(q, name) 81
82salsa::query_group! {
83 pub(crate) trait SyntaxDatabase: FilesDatabase {
84 fn file_syntax(file_id: FileId) -> File {
85 type FileSyntaxQuery;
86 }
87 fn file_lines(file_id: FileId) -> Arc<LineIndex> {
88 type FileLinesQuery;
89 }
90 fn file_symbols(file_id: FileId) -> Arc<SymbolIndex> {
91 type FileSymbolsQuery;
92 }
84 } 93 }
85} 94}
95
96fn file_syntax(db: &impl SyntaxDatabase, file_id: FileId) -> File {
97 let text = db.file_text(file_id);
98 File::parse(&*text)
99}
100fn file_lines(db: &impl SyntaxDatabase, file_id: FileId) -> Arc<LineIndex> {
101 let text = db.file_text(file_id);
102 Arc::new(LineIndex::new(&*text))
103}
104fn file_symbols(db: &impl SyntaxDatabase, file_id: FileId) -> Arc<SymbolIndex> {
105 let syntax = db.file_syntax(file_id);
106 Arc::new(SymbolIndex::for_file(file_id, syntax))
107}
108
109// mod imp;
110
111// use std::{
112// sync::Arc,
113// };
114// use im;
115// use salsa;
116// use {FileId, imp::FileResolverImp};
117
118// #[derive(Debug, Default, Clone)]
119// pub(crate) struct State {
120// pub(crate) file_map: im::HashMap<FileId, Arc<String>>,
121// pub(crate) file_resolver: FileResolverImp
122// }
123
124// #[derive(Debug)]
125// pub(crate) struct Db {
126// imp: imp::Db,
127// }
128
129// #[derive(Clone, Copy)]
130// pub(crate) struct QueryCtx<'a> {
131// imp: &'a salsa::QueryCtx<State, imp::Data>,
132// }
133
134// pub(crate) struct Query<T, R>(pub(crate) u16, pub(crate) fn(QueryCtx, &T) -> R);
135
136// pub(crate) struct QueryRegistry {
137// imp: imp::QueryRegistry,
138// }
139
140// impl Default for Db {
141// fn default() -> Db {
142// Db::new()
143// }
144// }
145
146// impl Db {
147// pub(crate) fn new() -> Db {
148// let reg = QueryRegistry::new();
149// Db { imp: imp::Db::new(reg.imp) }
150// }
151// pub(crate) fn state(&self) -> &State {
152// self.imp.imp.ground_data()
153// }
154// pub(crate) fn with_changes(&self, new_state: State, changed_files: &[FileId], resolver_changed: bool) -> Db {
155// Db { imp: self.imp.with_changes(new_state, changed_files, resolver_changed) }
156// }
157// pub(crate) fn make_query<F: FnOnce(QueryCtx) -> R, R>(&self, f: F) -> R {
158// let ctx = QueryCtx { imp: &self.imp.imp.query_ctx() };
159// f(ctx)
160// }
161// #[allow(unused)]
162// pub(crate) fn trace_query<F: FnOnce(QueryCtx) -> R, R>(&self, f: F) -> (R, Vec<&'static str>) {
163// let ctx = QueryCtx { imp: &self.imp.imp.query_ctx() };
164// let res = f(ctx);
165// let trace = self.imp.extract_trace(ctx.imp);
166// (res, trace)
167// }
168// }
169
170// impl<'a> QueryCtx<'a> {
171// pub(crate) fn get<Q: imp::EvalQuery>(&self, q: Q, params: Q::Params) -> Arc<Q::Output> {
172// q.get(self, params)
173// }
174// }
175
176// pub(crate) fn file_text(ctx: QueryCtx, file_id: FileId) -> Arc<String> {
177// imp::file_text(ctx, file_id)
178// }
179
180// pub(crate) fn file_set(ctx: QueryCtx) -> Arc<(Vec<FileId>, FileResolverImp)> {
181// imp::file_set(ctx)
182// }
183// impl QueryRegistry {
184// fn new() -> QueryRegistry {
185// let mut reg = QueryRegistry { imp: imp::QueryRegistry::new() };
186// ::queries::register_queries(&mut reg);
187// ::module_map::register_queries(&mut reg);
188// reg
189// }
190// pub(crate) fn add<Q: imp::EvalQuery>(&mut self, q: Q, name: &'static str) {
191// self.imp.add(q, name)
192// }
193// }
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;
14extern crate rustc_hash; 14extern crate rustc_hash;
15 15
16mod symbol_index; 16mod symbol_index;
17mod module_map; 17// mod module_map;
18mod imp; 18mod imp;
19mod job; 19mod job;
20mod roots; 20mod roots;
21mod db; 21mod db;
22mod queries; 22// mod queries;
23mod descriptors; 23mod descriptors;
24 24
25use std::{ 25use 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 @@
1use std::{ 1use std::{
2 collections::{HashMap, HashSet},
2 sync::Arc, 3 sync::Arc,
3 panic, 4 panic,
4}; 5};
6use parking_lot::RwLock;
5 7
6use once_cell::sync::OnceCell; 8use once_cell::sync::OnceCell;
7use rayon::prelude::*; 9use rayon::prelude::*;
8use rustc_hash::FxHashMap; 10use salsa::Database;
9use ra_editor::LineIndex; 11use ra_editor::LineIndex;
10use ra_syntax::File; 12use ra_syntax::File;
11 13
@@ -14,7 +16,7 @@ use crate::{
14 imp::FileResolverImp, 16 imp::FileResolverImp,
15 symbol_index::SymbolIndex, 17 symbol_index::SymbolIndex,
16 descriptors::{ModuleDescriptor, ModuleTreeDescriptor}, 18 descriptors::{ModuleDescriptor, ModuleTreeDescriptor},
17 db::Db, 19 db::{self, FilesDatabase, SyntaxDatabase}
18}; 20};
19 21
20pub(crate) trait SourceRoot { 22pub(crate) trait SourceRoot {
@@ -25,9 +27,9 @@ pub(crate) trait SourceRoot {
25 fn symbols(&self, acc: &mut Vec<Arc<SymbolIndex>>); 27 fn symbols(&self, acc: &mut Vec<Arc<SymbolIndex>>);
26} 28}
27 29
28#[derive(Default, Debug)] 30#[derive(Default, Debug, Clone)]
29pub(crate) struct WritableSourceRoot { 31pub(crate) struct WritableSourceRoot {
30 db: Db, 32 db: Arc<RwLock<db::RootDatabase>>,
31} 33}
32 34
33impl WritableSourceRoot { 35impl WritableSourceRoot {
@@ -36,51 +38,61 @@ impl WritableSourceRoot {
36 changes: &mut dyn Iterator<Item=(FileId, Option<String>)>, 38 changes: &mut dyn Iterator<Item=(FileId, Option<String>)>,
37 file_resolver: Option<FileResolverImp>, 39 file_resolver: Option<FileResolverImp>,
38 ) -> WritableSourceRoot { 40 ) -> WritableSourceRoot {
39 let resolver_changed = file_resolver.is_some(); 41 let db = self.db.write();
40 let mut changed_files = Vec::new(); 42 let mut changed = HashSet::new();
41 let mut new_state = self.db.state().clone(); 43 let mut removed = HashSet::new();
42
43 for (file_id, text) in changes { 44 for (file_id, text) in changes {
44 changed_files.push(file_id);
45 match text { 45 match text {
46 Some(text) => {
47 new_state.file_map.insert(file_id, Arc::new(text));
48 },
49 None => { 46 None => {
50 new_state.file_map.remove(&file_id); 47 removed.insert(file_id);
48 }
49 Some(text) => {
50 db.query(db::FileTextQuery)
51 .set(file_id, Arc::new(text));
52 changed.insert(file_id);
51 } 53 }
52 } 54 }
53 } 55 }
54 if let Some(file_resolver) = file_resolver { 56 if let Some(resolver) = file_resolver {
55 new_state.file_resolver = file_resolver 57 let mut files: HashSet<FileId> = db.file_set(())
56 } 58 .files
57 WritableSourceRoot { 59 .clone();
58 db: self.db.with_changes(new_state, &changed_files, resolver_changed) 60 for file_id in removed {
61 files.remove(&file_id);
62 }
63 files.extend(changed);
64 db.query(db::FileSetQuery)
65 .set((), Arc::new(db::FileSet { files, resolver }))
59 } 66 }
67 // TODO: reconcile sasla's API with our needs
68 // https://github.com/salsa-rs/salsa/issues/12
69 self.clone()
60 } 70 }
61} 71}
62 72
63impl SourceRoot for WritableSourceRoot { 73impl SourceRoot for WritableSourceRoot {
64 fn module_tree(&self) -> Arc<ModuleTreeDescriptor> { 74 fn module_tree(&self) -> Arc<ModuleTreeDescriptor> {
65 self.db.make_query(crate::module_map::module_tree) 75 unimplemented!()
76 //self.db.make_query(::module_map::module_tree)
66 } 77 }
67 78
68 fn contains(&self, file_id: FileId) -> bool { 79 fn contains(&self, file_id: FileId) -> bool {
69 self.db.state().file_map.contains_key(&file_id) 80 self.db.read().file_set(()).files.contains(&file_id)
70 } 81 }
71 fn lines(&self, file_id: FileId) -> Arc<LineIndex> { 82 fn lines(&self, file_id: FileId) -> Arc<LineIndex> {
72 self.db.make_query(|ctx| crate::queries::file_lines(ctx, file_id)) 83 self.db.read().file_lines(file_id)
73 } 84 }
74 fn syntax(&self, file_id: FileId) -> File { 85 fn syntax(&self, file_id: FileId) -> File {
75 self.db.make_query(|ctx| crate::queries::file_syntax(ctx, file_id)) 86 self.db.read().file_syntax(file_id)
76 } 87 }
77 fn symbols<'a>(&'a self, acc: &mut Vec<Arc<SymbolIndex>>) { 88 fn symbols<'a>(&'a self, acc: &mut Vec<Arc<SymbolIndex>>) {
78 self.db.make_query(|ctx| { 89 let db = self.db.read();
79 let file_set = crate::queries::file_set(ctx); 90 let symbols = db.file_set(());
80 let syms = file_set.0.iter() 91 let symbols = symbols
81 .map(|file_id| crate::queries::file_symbols(ctx, *file_id)); 92 .files
82 acc.extend(syms); 93 .iter()
83 }); 94 .map(|&file_id| db.file_symbols(file_id));
95 acc.extend(symbols);
84 } 96 }
85} 97}
86 98
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 {
17 map: fst::Map, 17 map: fst::Map,
18} 18}
19 19
20impl PartialEq for SymbolIndex {
21 fn eq(&self, other: &SymbolIndex) -> bool {
22 self.symbols == other.symbols
23 }
24}
25
26impl Eq for SymbolIndex {
27}
28
20impl Hash for SymbolIndex { 29impl Hash for SymbolIndex {
21 fn hash<H: Hasher>(&self, hasher: &mut H) { 30 fn hash<H: Hasher>(&self, hasher: &mut H) {
22 self.symbols.hash(hasher) 31 self.symbols.hash(hasher)
diff --git a/crates/ra_editor/src/line_index.rs b/crates/ra_editor/src/line_index.rs
index 6ccfdbd83..95d64b8a8 100644
--- a/crates/ra_editor/src/line_index.rs
+++ b/crates/ra_editor/src/line_index.rs
@@ -1,7 +1,7 @@
1use superslice::Ext; 1use superslice::Ext;
2use crate::TextUnit; 2use crate::TextUnit;
3 3
4#[derive(Clone, Debug, Hash)] 4#[derive(Clone, Debug, Hash, PartialEq, Eq)]
5pub struct LineIndex { 5pub struct LineIndex {
6 newlines: Vec<TextUnit>, 6 newlines: Vec<TextUnit>,
7} 7}
diff --git a/crates/ra_editor/src/symbols.rs b/crates/ra_editor/src/symbols.rs
index 6211ed547..d9e4b2df7 100644
--- a/crates/ra_editor/src/symbols.rs
+++ b/crates/ra_editor/src/symbols.rs
@@ -17,7 +17,7 @@ pub struct StructureNode {
17 pub kind: SyntaxKind, 17 pub kind: SyntaxKind,
18} 18}
19 19
20#[derive(Debug, Clone, Hash)] 20#[derive(Debug, Clone, PartialEq, Eq, Hash)]
21pub struct FileSymbol { 21pub struct FileSymbol {
22 pub name: SmolStr, 22 pub name: SmolStr,
23 pub node_range: TextRange, 23 pub node_range: TextRange,
diff --git a/crates/ra_syntax/src/lib.rs b/crates/ra_syntax/src/lib.rs
index 5bb54aba1..7eba5ee61 100644
--- a/crates/ra_syntax/src/lib.rs
+++ b/crates/ra_syntax/src/lib.rs
@@ -59,7 +59,7 @@ use crate::{
59 yellow::{GreenNode}, 59 yellow::{GreenNode},
60}; 60};
61 61
62#[derive(Clone, Debug, Hash)] 62#[derive(Clone, Debug, Hash, PartialEq, Eq)]
63pub struct File { 63pub struct File {
64 root: SyntaxNode 64 root: SyntaxNode
65} 65}