diff options
22 files changed, 352 insertions, 293 deletions
diff --git a/Cargo.lock b/Cargo.lock index b4d466fb6..5113317b0 100644 --- a/Cargo.lock +++ b/Cargo.lock | |||
@@ -607,6 +607,7 @@ dependencies = [ | |||
607 | "id-arena 1.0.2 (git+https://github.com/fitzgen/id-arena/?rev=43ecd67)", | 607 | "id-arena 1.0.2 (git+https://github.com/fitzgen/id-arena/?rev=43ecd67)", |
608 | "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", | 608 | "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", |
609 | "parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", | 609 | "parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", |
610 | "ra_db 0.1.0", | ||
610 | "ra_editor 0.1.0", | 611 | "ra_editor 0.1.0", |
611 | "ra_syntax 0.1.0", | 612 | "ra_syntax 0.1.0", |
612 | "rayon 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", | 613 | "rayon 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", |
@@ -629,6 +630,21 @@ dependencies = [ | |||
629 | ] | 630 | ] |
630 | 631 | ||
631 | [[package]] | 632 | [[package]] |
633 | name = "ra_db" | ||
634 | version = "0.1.0" | ||
635 | dependencies = [ | ||
636 | "id-arena 1.0.2 (git+https://github.com/fitzgen/id-arena/?rev=43ecd67)", | ||
637 | "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", | ||
638 | "parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", | ||
639 | "ra_editor 0.1.0", | ||
640 | "ra_syntax 0.1.0", | ||
641 | "relative-path 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", | ||
642 | "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", | ||
643 | "salsa 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", | ||
644 | "test_utils 0.1.0", | ||
645 | ] | ||
646 | |||
647 | [[package]] | ||
632 | name = "ra_editor" | 648 | name = "ra_editor" |
633 | version = "0.1.0" | 649 | version = "0.1.0" |
634 | dependencies = [ | 650 | dependencies = [ |
diff --git a/crates/ra_analysis/Cargo.toml b/crates/ra_analysis/Cargo.toml index 5dae45857..48d8e56e3 100644 --- a/crates/ra_analysis/Cargo.toml +++ b/crates/ra_analysis/Cargo.toml | |||
@@ -15,4 +15,5 @@ parking_lot = "0.6.4" | |||
15 | id-arena = { git = "https://github.com/fitzgen/id-arena/", rev = "43ecd67" } | 15 | id-arena = { git = "https://github.com/fitzgen/id-arena/", rev = "43ecd67" } |
16 | ra_syntax = { path = "../ra_syntax" } | 16 | ra_syntax = { path = "../ra_syntax" } |
17 | ra_editor = { path = "../ra_editor" } | 17 | ra_editor = { path = "../ra_editor" } |
18 | ra_db = { path = "../ra_db" } | ||
18 | test_utils = { path = "../test_utils" } | 19 | test_utils = { path = "../test_utils" } |
diff --git a/crates/ra_analysis/src/completion/mod.rs b/crates/ra_analysis/src/completion/mod.rs index 844dabb19..538b51633 100644 --- a/crates/ra_analysis/src/completion/mod.rs +++ b/crates/ra_analysis/src/completion/mod.rs | |||
@@ -7,10 +7,11 @@ use ra_syntax::{ | |||
7 | AstNode, AtomEdit, | 7 | AstNode, AtomEdit, |
8 | SyntaxNodeRef, | 8 | SyntaxNodeRef, |
9 | }; | 9 | }; |
10 | use ra_db::SyntaxDatabase; | ||
10 | use rustc_hash::{FxHashMap}; | 11 | use rustc_hash::{FxHashMap}; |
11 | 12 | ||
12 | use crate::{ | 13 | use crate::{ |
13 | db::{self, SyntaxDatabase}, | 14 | db, |
14 | hir, | 15 | hir, |
15 | Cancelable, FilePosition | 16 | Cancelable, FilePosition |
16 | }; | 17 | }; |
diff --git a/crates/ra_analysis/src/db.rs b/crates/ra_analysis/src/db.rs index e0b7afac5..1b2dd4b3d 100644 --- a/crates/ra_analysis/src/db.rs +++ b/crates/ra_analysis/src/db.rs | |||
@@ -1,15 +1,13 @@ | |||
1 | use std::sync::Arc; | 1 | use std::sync::Arc; |
2 | #[cfg(test)] | 2 | #[cfg(test)] |
3 | use parking_lot::Mutex; | 3 | use parking_lot::Mutex; |
4 | use ra_editor::LineIndex; | ||
5 | use ra_syntax::{SourceFileNode}; | ||
6 | use salsa::{self, Database}; | 4 | use salsa::{self, Database}; |
5 | use ra_db::{LocationIntener, BaseDatabase}; | ||
7 | 6 | ||
8 | use crate::{ | 7 | use crate::{ |
9 | hir, | 8 | hir, |
10 | symbol_index, | 9 | symbol_index, |
11 | loc2id::{IdMaps, LocationIntener, DefId, DefLoc, FnId}, | 10 | loc2id::{IdMaps, DefId, DefLoc, FnId}, |
12 | Cancelable, Canceled, FileId, | ||
13 | }; | 11 | }; |
14 | 12 | ||
15 | #[derive(Debug)] | 13 | #[derive(Debug)] |
@@ -47,11 +45,11 @@ impl Default for RootDatabase { | |||
47 | runtime: salsa::Runtime::default(), | 45 | runtime: salsa::Runtime::default(), |
48 | id_maps: Default::default(), | 46 | id_maps: Default::default(), |
49 | }; | 47 | }; |
50 | db.query_mut(crate::input::SourceRootQuery) | 48 | db.query_mut(ra_db::SourceRootQuery) |
51 | .set(crate::input::WORKSPACE, Default::default()); | 49 | .set(ra_db::WORKSPACE, Default::default()); |
52 | db.query_mut(crate::input::CrateGraphQuery) | 50 | db.query_mut(ra_db::CrateGraphQuery) |
53 | .set((), Default::default()); | 51 | .set((), Default::default()); |
54 | db.query_mut(crate::input::LibrariesQuery) | 52 | db.query_mut(ra_db::LibrariesQuery) |
55 | .set((), Default::default()); | 53 | .set((), Default::default()); |
56 | db | 54 | db |
57 | } | 55 | } |
@@ -67,22 +65,7 @@ impl salsa::ParallelDatabase for RootDatabase { | |||
67 | } | 65 | } |
68 | } | 66 | } |
69 | 67 | ||
70 | pub(crate) trait BaseDatabase: salsa::Database { | 68 | impl BaseDatabase for RootDatabase {} |
71 | fn id_maps(&self) -> &IdMaps; | ||
72 | fn check_canceled(&self) -> Cancelable<()> { | ||
73 | if self.salsa_runtime().is_current_revision_canceled() { | ||
74 | Err(Canceled) | ||
75 | } else { | ||
76 | Ok(()) | ||
77 | } | ||
78 | } | ||
79 | } | ||
80 | |||
81 | impl BaseDatabase for RootDatabase { | ||
82 | fn id_maps(&self) -> &IdMaps { | ||
83 | &self.id_maps | ||
84 | } | ||
85 | } | ||
86 | 69 | ||
87 | impl AsRef<LocationIntener<DefLoc, DefId>> for RootDatabase { | 70 | impl AsRef<LocationIntener<DefLoc, DefId>> for RootDatabase { |
88 | fn as_ref(&self) -> &LocationIntener<DefLoc, DefId> { | 71 | fn as_ref(&self) -> &LocationIntener<DefLoc, DefId> { |
@@ -121,16 +104,16 @@ impl RootDatabase { | |||
121 | 104 | ||
122 | salsa::database_storage! { | 105 | salsa::database_storage! { |
123 | pub(crate) struct RootDatabaseStorage for RootDatabase { | 106 | pub(crate) struct RootDatabaseStorage for RootDatabase { |
124 | impl crate::input::FilesDatabase { | 107 | impl ra_db::FilesDatabase { |
125 | fn file_text() for crate::input::FileTextQuery; | 108 | fn file_text() for ra_db::FileTextQuery; |
126 | fn file_source_root() for crate::input::FileSourceRootQuery; | 109 | fn file_source_root() for ra_db::FileSourceRootQuery; |
127 | fn source_root() for crate::input::SourceRootQuery; | 110 | fn source_root() for ra_db::SourceRootQuery; |
128 | fn libraries() for crate::input::LibrariesQuery; | 111 | fn libraries() for ra_db::LibrariesQuery; |
129 | fn crate_graph() for crate::input::CrateGraphQuery; | 112 | fn crate_graph() for ra_db::CrateGraphQuery; |
130 | } | 113 | } |
131 | impl SyntaxDatabase { | 114 | impl ra_db::SyntaxDatabase { |
132 | fn source_file() for SourceFileQuery; | 115 | fn source_file() for ra_db::SourceFileQuery; |
133 | fn file_lines() for FileLinesQuery; | 116 | fn file_lines() for ra_db::FileLinesQuery; |
134 | } | 117 | } |
135 | impl symbol_index::SymbolsDatabase { | 118 | impl symbol_index::SymbolsDatabase { |
136 | fn file_symbols() for symbol_index::FileSymbolsQuery; | 119 | fn file_symbols() for symbol_index::FileSymbolsQuery; |
@@ -148,23 +131,3 @@ salsa::database_storage! { | |||
148 | } | 131 | } |
149 | } | 132 | } |
150 | } | 133 | } |
151 | |||
152 | salsa::query_group! { | ||
153 | pub(crate) trait SyntaxDatabase: crate::input::FilesDatabase + BaseDatabase { | ||
154 | fn source_file(file_id: FileId) -> SourceFileNode { | ||
155 | type SourceFileQuery; | ||
156 | } | ||
157 | fn file_lines(file_id: FileId) -> Arc<LineIndex> { | ||
158 | type FileLinesQuery; | ||
159 | } | ||
160 | } | ||
161 | } | ||
162 | |||
163 | fn source_file(db: &impl SyntaxDatabase, file_id: FileId) -> SourceFileNode { | ||
164 | let text = db.file_text(file_id); | ||
165 | SourceFileNode::parse(&*text) | ||
166 | } | ||
167 | fn file_lines(db: &impl SyntaxDatabase, file_id: FileId) -> Arc<LineIndex> { | ||
168 | let text = db.file_text(file_id); | ||
169 | Arc::new(LineIndex::new(&*text)) | ||
170 | } | ||
diff --git a/crates/ra_analysis/src/hir/db.rs b/crates/ra_analysis/src/hir/db.rs index bf0dc393a..0ae2086ff 100644 --- a/crates/ra_analysis/src/hir/db.rs +++ b/crates/ra_analysis/src/hir/db.rs | |||
@@ -4,10 +4,10 @@ use ra_syntax::{ | |||
4 | SyntaxNode, | 4 | SyntaxNode, |
5 | ast::FnDefNode, | 5 | ast::FnDefNode, |
6 | }; | 6 | }; |
7 | use ra_db::{SourceRootId, LocationIntener, SyntaxDatabase}; | ||
7 | 8 | ||
8 | use crate::{ | 9 | use crate::{ |
9 | FileId, | 10 | FileId, |
10 | db::SyntaxDatabase, | ||
11 | hir::{ | 11 | hir::{ |
12 | SourceFileItems, SourceItemId, | 12 | SourceFileItems, SourceItemId, |
13 | query_definitions, | 13 | query_definitions, |
@@ -15,8 +15,7 @@ use crate::{ | |||
15 | module::{ModuleId, ModuleTree, ModuleSource, | 15 | module::{ModuleId, ModuleTree, ModuleSource, |
16 | nameres::{ItemMap, InputModuleItems}}, | 16 | nameres::{ItemMap, InputModuleItems}}, |
17 | }, | 17 | }, |
18 | input::SourceRootId, | 18 | loc2id::{DefLoc, DefId, FnId}, |
19 | loc2id::{DefLoc, DefId, FnId, LocationIntener}, | ||
20 | Cancelable, | 19 | Cancelable, |
21 | }; | 20 | }; |
22 | 21 | ||
diff --git a/crates/ra_analysis/src/hir/function/scope.rs b/crates/ra_analysis/src/hir/function/scope.rs index 76b2fea68..ed789fede 100644 --- a/crates/ra_analysis/src/hir/function/scope.rs +++ b/crates/ra_analysis/src/hir/function/scope.rs | |||
@@ -5,9 +5,10 @@ use ra_syntax::{ | |||
5 | algo::generate, | 5 | algo::generate, |
6 | ast::{self, ArgListOwner, LoopBodyOwner, NameOwner}, | 6 | ast::{self, ArgListOwner, LoopBodyOwner, NameOwner}, |
7 | }; | 7 | }; |
8 | use ra_db::LocalSyntaxPtr; | ||
8 | 9 | ||
9 | use crate::{ | 10 | use crate::{ |
10 | syntax_ptr::LocalSyntaxPtr, | 11 | |
11 | arena::{Arena, Id}, | 12 | arena::{Arena, Id}, |
12 | }; | 13 | }; |
13 | 14 | ||
diff --git a/crates/ra_analysis/src/hir/module/imp.rs b/crates/ra_analysis/src/hir/module/imp.rs index d51ca2d59..c8f7ed58d 100644 --- a/crates/ra_analysis/src/hir/module/imp.rs +++ b/crates/ra_analysis/src/hir/module/imp.rs | |||
@@ -6,11 +6,11 @@ use ra_syntax::{ | |||
6 | }; | 6 | }; |
7 | use relative_path::RelativePathBuf; | 7 | use relative_path::RelativePathBuf; |
8 | use rustc_hash::{FxHashMap, FxHashSet}; | 8 | use rustc_hash::{FxHashMap, FxHashSet}; |
9 | use ra_db::{SourceRoot, SourceRootId, FileResolverImp}; | ||
9 | 10 | ||
10 | use crate::{ | 11 | use crate::{ |
11 | hir::HirDatabase, | 12 | hir::HirDatabase, |
12 | input::{SourceRoot, SourceRootId}, | 13 | Cancelable, FileId, |
13 | Cancelable, FileId, FileResolverImp, | ||
14 | }; | 14 | }; |
15 | 15 | ||
16 | use super::{ | 16 | use super::{ |
diff --git a/crates/ra_analysis/src/hir/module/mod.rs b/crates/ra_analysis/src/hir/module/mod.rs index 893ec3a10..683cb5d4c 100644 --- a/crates/ra_analysis/src/hir/module/mod.rs +++ b/crates/ra_analysis/src/hir/module/mod.rs | |||
@@ -10,12 +10,12 @@ use ra_syntax::{ | |||
10 | ast::{self, AstNode, NameOwner}, | 10 | ast::{self, AstNode, NameOwner}, |
11 | SmolStr, SyntaxNode, | 11 | SmolStr, SyntaxNode, |
12 | }; | 12 | }; |
13 | use ra_db::SourceRootId; | ||
13 | use relative_path::RelativePathBuf; | 14 | use relative_path::RelativePathBuf; |
14 | 15 | ||
15 | use crate::{ | 16 | use crate::{ |
16 | FileId, FilePosition, Cancelable, | 17 | FileId, FilePosition, Cancelable, |
17 | hir::{Path, PathKind, HirDatabase, SourceItemId}, | 18 | hir::{Path, PathKind, HirDatabase, SourceItemId}, |
18 | input::SourceRootId, | ||
19 | arena::{Arena, Id}, | 19 | arena::{Arena, Id}, |
20 | loc2id::{DefLoc, DefId}, | 20 | loc2id::{DefLoc, DefId}, |
21 | }; | 21 | }; |
diff --git a/crates/ra_analysis/src/hir/module/nameres.rs b/crates/ra_analysis/src/hir/module/nameres.rs index f48f51c8d..5c87e7af2 100644 --- a/crates/ra_analysis/src/hir/module/nameres.rs +++ b/crates/ra_analysis/src/hir/module/nameres.rs | |||
@@ -19,12 +19,12 @@ use std::{ | |||
19 | }; | 19 | }; |
20 | 20 | ||
21 | use rustc_hash::FxHashMap; | 21 | use rustc_hash::FxHashMap; |
22 | |||
23 | use ra_syntax::{ | 22 | use ra_syntax::{ |
24 | TextRange, | 23 | TextRange, |
25 | SmolStr, SyntaxKind::{self, *}, | 24 | SmolStr, SyntaxKind::{self, *}, |
26 | ast::{self, AstNode} | 25 | ast::{self, AstNode} |
27 | }; | 26 | }; |
27 | use ra_db::SourceRootId; | ||
28 | 28 | ||
29 | use crate::{ | 29 | use crate::{ |
30 | Cancelable, FileId, | 30 | Cancelable, FileId, |
@@ -35,7 +35,6 @@ use crate::{ | |||
35 | HirDatabase, | 35 | HirDatabase, |
36 | module::{ModuleId, ModuleTree}, | 36 | module::{ModuleId, ModuleTree}, |
37 | }, | 37 | }, |
38 | input::SourceRootId, | ||
39 | }; | 38 | }; |
40 | 39 | ||
41 | /// Item map is the result of the name resolution. Item map contains, for each | 40 | /// Item map is the result of the name resolution. Item map contains, for each |
@@ -342,11 +341,11 @@ where | |||
342 | 341 | ||
343 | #[cfg(test)] | 342 | #[cfg(test)] |
344 | mod tests { | 343 | mod tests { |
344 | use ra_db::FilesDatabase; | ||
345 | use crate::{ | 345 | use crate::{ |
346 | AnalysisChange, | 346 | AnalysisChange, |
347 | mock_analysis::{MockAnalysis, analysis_and_position}, | 347 | mock_analysis::{MockAnalysis, analysis_and_position}, |
348 | hir::{self, HirDatabase}, | 348 | hir::{self, HirDatabase}, |
349 | input::FilesDatabase, | ||
350 | }; | 349 | }; |
351 | use super::*; | 350 | use super::*; |
352 | 351 | ||
diff --git a/crates/ra_analysis/src/hir/query_definitions.rs b/crates/ra_analysis/src/hir/query_definitions.rs index 6570ca994..fbdf8eb67 100644 --- a/crates/ra_analysis/src/hir/query_definitions.rs +++ b/crates/ra_analysis/src/hir/query_definitions.rs | |||
@@ -8,6 +8,7 @@ use ra_syntax::{ | |||
8 | AstNode, SyntaxNode, SmolStr, | 8 | AstNode, SyntaxNode, SmolStr, |
9 | ast::{self, FnDef, FnDefNode, NameOwner, ModuleItemOwner} | 9 | ast::{self, FnDef, FnDefNode, NameOwner, ModuleItemOwner} |
10 | }; | 10 | }; |
11 | use ra_db::SourceRootId; | ||
11 | 12 | ||
12 | use crate::{ | 13 | use crate::{ |
13 | FileId, Cancelable, | 14 | FileId, Cancelable, |
@@ -21,7 +22,6 @@ use crate::{ | |||
21 | nameres::{InputModuleItems, ItemMap, Resolver}, | 22 | nameres::{InputModuleItems, ItemMap, Resolver}, |
22 | }, | 23 | }, |
23 | }, | 24 | }, |
24 | input::SourceRootId, | ||
25 | }; | 25 | }; |
26 | 26 | ||
27 | /// Resolve `FnId` to the corresponding `SyntaxNode` | 27 | /// Resolve `FnId` to the corresponding `SyntaxNode` |
diff --git a/crates/ra_analysis/src/imp.rs b/crates/ra_analysis/src/imp.rs index c86bc111a..9a8694221 100644 --- a/crates/ra_analysis/src/imp.rs +++ b/crates/ra_analysis/src/imp.rs | |||
@@ -1,6 +1,5 @@ | |||
1 | use std::{ | 1 | use std::{ |
2 | fmt, | 2 | fmt, |
3 | hash::{Hash, Hasher}, | ||
4 | sync::Arc, | 3 | sync::Arc, |
5 | }; | 4 | }; |
6 | 5 | ||
@@ -11,84 +10,24 @@ use ra_syntax::{ | |||
11 | SyntaxKind::*, | 10 | SyntaxKind::*, |
12 | SyntaxNodeRef, TextRange, TextUnit, | 11 | SyntaxNodeRef, TextRange, TextUnit, |
13 | }; | 12 | }; |
13 | use ra_db::{FilesDatabase, SourceRoot, SourceRootId, WORKSPACE, SyntaxDatabase, SourceFileQuery}; | ||
14 | use rayon::prelude::*; | 14 | use rayon::prelude::*; |
15 | use relative_path::RelativePath; | ||
16 | use rustc_hash::FxHashSet; | 15 | use rustc_hash::FxHashSet; |
17 | use salsa::{Database, ParallelDatabase}; | 16 | use salsa::{Database, ParallelDatabase}; |
18 | 17 | ||
19 | use crate::{ | 18 | use crate::{ |
20 | completion::{completions, CompletionItem}, | 19 | completion::{completions, CompletionItem}, |
21 | db::{self, SourceFileQuery, SyntaxDatabase}, | 20 | db, |
22 | hir::{ | 21 | hir::{ |
23 | self, | 22 | self, |
24 | FnSignatureInfo, | 23 | FnSignatureInfo, |
25 | Problem, | 24 | Problem, |
26 | }, | 25 | }, |
27 | input::{FilesDatabase, SourceRoot, SourceRootId, WORKSPACE}, | ||
28 | symbol_index::{SymbolIndex, SymbolsDatabase}, | 26 | symbol_index::{SymbolIndex, SymbolsDatabase}, |
29 | AnalysisChange, Cancelable, CrateGraph, CrateId, Diagnostic, FileId, FileResolver, | 27 | AnalysisChange, Cancelable, CrateId, Diagnostic, FileId, |
30 | FileSystemEdit, FilePosition, Query, SourceChange, SourceFileNodeEdit, | 28 | FileSystemEdit, FilePosition, Query, SourceChange, SourceFileNodeEdit, |
31 | }; | 29 | }; |
32 | 30 | ||
33 | #[derive(Clone, Debug)] | ||
34 | pub(crate) struct FileResolverImp { | ||
35 | inner: Arc<FileResolver>, | ||
36 | } | ||
37 | |||
38 | impl PartialEq for FileResolverImp { | ||
39 | fn eq(&self, other: &FileResolverImp) -> bool { | ||
40 | self.inner() == other.inner() | ||
41 | } | ||
42 | } | ||
43 | |||
44 | impl Eq for FileResolverImp {} | ||
45 | |||
46 | impl Hash for FileResolverImp { | ||
47 | fn hash<H: Hasher>(&self, hasher: &mut H) { | ||
48 | self.inner().hash(hasher); | ||
49 | } | ||
50 | } | ||
51 | |||
52 | impl FileResolverImp { | ||
53 | pub(crate) fn new(inner: Arc<FileResolver>) -> FileResolverImp { | ||
54 | FileResolverImp { inner } | ||
55 | } | ||
56 | pub(crate) fn file_stem(&self, file_id: FileId) -> String { | ||
57 | self.inner.file_stem(file_id) | ||
58 | } | ||
59 | pub(crate) fn resolve(&self, file_id: FileId, path: &RelativePath) -> Option<FileId> { | ||
60 | self.inner.resolve(file_id, path) | ||
61 | } | ||
62 | pub(crate) fn debug_path(&self, file_id: FileId) -> Option<std::path::PathBuf> { | ||
63 | self.inner.debug_path(file_id) | ||
64 | } | ||
65 | fn inner(&self) -> *const FileResolver { | ||
66 | &*self.inner | ||
67 | } | ||
68 | } | ||
69 | |||
70 | impl Default for FileResolverImp { | ||
71 | fn default() -> FileResolverImp { | ||
72 | #[derive(Debug)] | ||
73 | struct DummyResolver; | ||
74 | impl FileResolver for DummyResolver { | ||
75 | fn file_stem(&self, _file_: FileId) -> String { | ||
76 | panic!("file resolver not set") | ||
77 | } | ||
78 | fn resolve( | ||
79 | &self, | ||
80 | _file_id: FileId, | ||
81 | _path: &::relative_path::RelativePath, | ||
82 | ) -> Option<FileId> { | ||
83 | panic!("file resolver not set") | ||
84 | } | ||
85 | } | ||
86 | FileResolverImp { | ||
87 | inner: Arc::new(DummyResolver), | ||
88 | } | ||
89 | } | ||
90 | } | ||
91 | |||
92 | #[derive(Debug, Default)] | 31 | #[derive(Debug, Default)] |
93 | pub(crate) struct AnalysisHostImpl { | 32 | pub(crate) struct AnalysisHostImpl { |
94 | db: db::RootDatabase, | 33 | db: db::RootDatabase, |
@@ -105,7 +44,7 @@ impl AnalysisHostImpl { | |||
105 | 44 | ||
106 | for (file_id, text) in change.files_changed { | 45 | for (file_id, text) in change.files_changed { |
107 | self.db | 46 | self.db |
108 | .query_mut(crate::input::FileTextQuery) | 47 | .query_mut(ra_db::FileTextQuery) |
109 | .set(file_id, Arc::new(text)) | 48 | .set(file_id, Arc::new(text)) |
110 | } | 49 | } |
111 | if !(change.files_added.is_empty() && change.files_removed.is_empty()) { | 50 | if !(change.files_added.is_empty() && change.files_removed.is_empty()) { |
@@ -115,22 +54,22 @@ impl AnalysisHostImpl { | |||
115 | let mut source_root = SourceRoot::clone(&self.db.source_root(WORKSPACE)); | 54 | let mut source_root = SourceRoot::clone(&self.db.source_root(WORKSPACE)); |
116 | for (file_id, text) in change.files_added { | 55 | for (file_id, text) in change.files_added { |
117 | self.db | 56 | self.db |
118 | .query_mut(crate::input::FileTextQuery) | 57 | .query_mut(ra_db::FileTextQuery) |
119 | .set(file_id, Arc::new(text)); | 58 | .set(file_id, Arc::new(text)); |
120 | self.db | 59 | self.db |
121 | .query_mut(crate::input::FileSourceRootQuery) | 60 | .query_mut(ra_db::FileSourceRootQuery) |
122 | .set(file_id, crate::input::WORKSPACE); | 61 | .set(file_id, ra_db::WORKSPACE); |
123 | source_root.files.insert(file_id); | 62 | source_root.files.insert(file_id); |
124 | } | 63 | } |
125 | for file_id in change.files_removed { | 64 | for file_id in change.files_removed { |
126 | self.db | 65 | self.db |
127 | .query_mut(crate::input::FileTextQuery) | 66 | .query_mut(ra_db::FileTextQuery) |
128 | .set(file_id, Arc::new(String::new())); | 67 | .set(file_id, Arc::new(String::new())); |
129 | source_root.files.remove(&file_id); | 68 | source_root.files.remove(&file_id); |
130 | } | 69 | } |
131 | source_root.file_resolver = file_resolver; | 70 | source_root.file_resolver = file_resolver; |
132 | self.db | 71 | self.db |
133 | .query_mut(crate::input::SourceRootQuery) | 72 | .query_mut(ra_db::SourceRootQuery) |
134 | .set(WORKSPACE, Arc::new(source_root)) | 73 | .set(WORKSPACE, Arc::new(source_root)) |
135 | } | 74 | } |
136 | if !change.libraries_added.is_empty() { | 75 | if !change.libraries_added.is_empty() { |
@@ -147,10 +86,10 @@ impl AnalysisHostImpl { | |||
147 | library.file_resolver.debug_path(file_id) | 86 | library.file_resolver.debug_path(file_id) |
148 | ); | 87 | ); |
149 | self.db | 88 | self.db |
150 | .query_mut(crate::input::FileSourceRootQuery) | 89 | .query_mut(ra_db::FileSourceRootQuery) |
151 | .set_constant(file_id, source_root_id); | 90 | .set_constant(file_id, source_root_id); |
152 | self.db | 91 | self.db |
153 | .query_mut(crate::input::FileTextQuery) | 92 | .query_mut(ra_db::FileTextQuery) |
154 | .set_constant(file_id, Arc::new(text)); | 93 | .set_constant(file_id, Arc::new(text)); |
155 | } | 94 | } |
156 | let source_root = SourceRoot { | 95 | let source_root = SourceRoot { |
@@ -158,19 +97,19 @@ impl AnalysisHostImpl { | |||
158 | file_resolver: library.file_resolver, | 97 | file_resolver: library.file_resolver, |
159 | }; | 98 | }; |
160 | self.db | 99 | self.db |
161 | .query_mut(crate::input::SourceRootQuery) | 100 | .query_mut(ra_db::SourceRootQuery) |
162 | .set(source_root_id, Arc::new(source_root)); | 101 | .set(source_root_id, Arc::new(source_root)); |
163 | self.db | 102 | self.db |
164 | .query_mut(crate::symbol_index::LibrarySymbolsQuery) | 103 | .query_mut(crate::symbol_index::LibrarySymbolsQuery) |
165 | .set(source_root_id, Arc::new(library.symbol_index)); | 104 | .set(source_root_id, Arc::new(library.symbol_index)); |
166 | } | 105 | } |
167 | self.db | 106 | self.db |
168 | .query_mut(crate::input::LibrariesQuery) | 107 | .query_mut(ra_db::LibrariesQuery) |
169 | .set((), Arc::new(libraries)); | 108 | .set((), Arc::new(libraries)); |
170 | } | 109 | } |
171 | if let Some(crate_graph) = change.crate_graph { | 110 | if let Some(crate_graph) = change.crate_graph { |
172 | self.db | 111 | self.db |
173 | .query_mut(crate::input::CrateGraphQuery) | 112 | .query_mut(ra_db::CrateGraphQuery) |
174 | .set((), Arc::new(crate_graph)) | 113 | .set((), Arc::new(crate_graph)) |
175 | } | 114 | } |
176 | } | 115 | } |
@@ -261,7 +200,7 @@ impl AnalysisImpl { | |||
261 | Ok(crate_id.into_iter().collect()) | 200 | Ok(crate_id.into_iter().collect()) |
262 | } | 201 | } |
263 | pub fn crate_root(&self, crate_id: CrateId) -> FileId { | 202 | pub fn crate_root(&self, crate_id: CrateId) -> FileId { |
264 | self.db.crate_graph().crate_roots[&crate_id] | 203 | self.db.crate_graph().crate_root(crate_id) |
265 | } | 204 | } |
266 | pub fn completions(&self, position: FilePosition) -> Cancelable<Option<Vec<CompletionItem>>> { | 205 | pub fn completions(&self, position: FilePosition) -> Cancelable<Option<Vec<CompletionItem>>> { |
267 | completions(&self.db, position) | 206 | completions(&self.db, position) |
@@ -546,16 +485,6 @@ impl SourceChange { | |||
546 | } | 485 | } |
547 | } | 486 | } |
548 | 487 | ||
549 | impl CrateGraph { | ||
550 | fn crate_id_for_crate_root(&self, file_id: FileId) -> Option<CrateId> { | ||
551 | let (&crate_id, _) = self | ||
552 | .crate_roots | ||
553 | .iter() | ||
554 | .find(|(_crate_id, &root_id)| root_id == file_id)?; | ||
555 | Some(crate_id) | ||
556 | } | ||
557 | } | ||
558 | |||
559 | enum FnCallNode<'a> { | 488 | enum FnCallNode<'a> { |
560 | CallExpr(ast::CallExpr<'a>), | 489 | CallExpr(ast::CallExpr<'a>), |
561 | MethodCallExpr(ast::MethodCallExpr<'a>), | 490 | MethodCallExpr(ast::MethodCallExpr<'a>), |
diff --git a/crates/ra_analysis/src/lib.rs b/crates/ra_analysis/src/lib.rs index c0e43544e..012d36b8e 100644 --- a/crates/ra_analysis/src/lib.rs +++ b/crates/ra_analysis/src/lib.rs | |||
@@ -19,8 +19,6 @@ macro_rules! ctry { | |||
19 | } | 19 | } |
20 | 20 | ||
21 | mod arena; | 21 | mod arena; |
22 | mod syntax_ptr; | ||
23 | mod input; | ||
24 | mod db; | 22 | mod db; |
25 | mod loc2id; | 23 | mod loc2id; |
26 | mod imp; | 24 | mod imp; |
@@ -32,35 +30,27 @@ pub mod mock_analysis; | |||
32 | use std::{fmt, sync::Arc}; | 30 | use std::{fmt, sync::Arc}; |
33 | 31 | ||
34 | use ra_syntax::{AtomEdit, SourceFileNode, TextRange, TextUnit}; | 32 | use ra_syntax::{AtomEdit, SourceFileNode, TextRange, TextUnit}; |
33 | use ra_db::FileResolverImp; | ||
35 | use rayon::prelude::*; | 34 | use rayon::prelude::*; |
36 | use relative_path::RelativePathBuf; | 35 | use relative_path::RelativePathBuf; |
37 | 36 | ||
38 | use crate::{ | 37 | use crate::{ |
39 | imp::{AnalysisHostImpl, AnalysisImpl, FileResolverImp}, | 38 | imp::{AnalysisHostImpl, AnalysisImpl}, |
40 | symbol_index::SymbolIndex, | 39 | symbol_index::SymbolIndex, |
41 | }; | 40 | }; |
42 | 41 | ||
43 | pub use crate::{ | 42 | pub use crate::{ |
44 | completion::CompletionItem, | 43 | completion::CompletionItem, |
45 | hir::FnSignatureInfo, | 44 | hir::FnSignatureInfo, |
46 | input::{CrateGraph, CrateId, FileId, FileResolver}, | ||
47 | }; | 45 | }; |
48 | pub use ra_editor::{ | 46 | pub use ra_editor::{ |
49 | FileSymbol, Fold, FoldKind, HighlightedRange, LineIndex, Runnable, RunnableKind, StructureNode, | 47 | FileSymbol, Fold, FoldKind, HighlightedRange, LineIndex, Runnable, RunnableKind, StructureNode, |
50 | }; | 48 | }; |
51 | 49 | ||
52 | #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)] | 50 | pub use ra_db::{ |
53 | pub struct Canceled; | 51 | Canceled, Cancelable, |
54 | 52 | CrateGraph, CrateId, FileId, FileResolver | |
55 | pub type Cancelable<T> = Result<T, Canceled>; | 53 | }; |
56 | |||
57 | impl std::fmt::Display for Canceled { | ||
58 | fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | ||
59 | fmt.write_str("Canceled") | ||
60 | } | ||
61 | } | ||
62 | |||
63 | impl std::error::Error for Canceled {} | ||
64 | 54 | ||
65 | #[derive(Default)] | 55 | #[derive(Default)] |
66 | pub struct AnalysisChange { | 56 | pub struct AnalysisChange { |
diff --git a/crates/ra_analysis/src/loc2id.rs b/crates/ra_analysis/src/loc2id.rs index 2aa141130..7956431ab 100644 --- a/crates/ra_analysis/src/loc2id.rs +++ b/crates/ra_analysis/src/loc2id.rs | |||
@@ -1,74 +1,10 @@ | |||
1 | use parking_lot::Mutex; | 1 | use ra_db::SourceRootId; |
2 | |||
3 | use std::hash::Hash; | ||
4 | |||
5 | use rustc_hash::FxHashMap; | ||
6 | 2 | ||
7 | use crate::{ | 3 | use crate::{ |
8 | hir::{SourceItemId, ModuleId}, | 4 | hir::{SourceItemId, ModuleId}, |
9 | input::SourceRootId, | ||
10 | }; | 5 | }; |
11 | 6 | ||
12 | /// There are two principle ways to refer to things: | 7 | use ra_db::{NumericId, LocationIntener}; |
13 | /// - by their locatinon (module in foo/bar/baz.rs at line 42) | ||
14 | /// - by their numeric id (module `ModuleId(42)`) | ||
15 | /// | ||
16 | /// The first one is more powerful (you can actually find the thing in question | ||
17 | /// by id), but the second one is so much more compact. | ||
18 | /// | ||
19 | /// `Loc2IdMap` allows us to have a cake an eat it as well: by maintaining a | ||
20 | /// bidirectional mapping between positional and numeric ids, we can use compact | ||
21 | /// representation wich still allows us to get the actual item | ||
22 | #[derive(Debug)] | ||
23 | struct Loc2IdMap<LOC, ID> | ||
24 | where | ||
25 | ID: NumericId, | ||
26 | LOC: Clone + Eq + Hash, | ||
27 | { | ||
28 | loc2id: FxHashMap<LOC, ID>, | ||
29 | id2loc: FxHashMap<ID, LOC>, | ||
30 | } | ||
31 | |||
32 | impl<LOC, ID> Default for Loc2IdMap<LOC, ID> | ||
33 | where | ||
34 | ID: NumericId, | ||
35 | LOC: Clone + Eq + Hash, | ||
36 | { | ||
37 | fn default() -> Self { | ||
38 | Loc2IdMap { | ||
39 | loc2id: FxHashMap::default(), | ||
40 | id2loc: FxHashMap::default(), | ||
41 | } | ||
42 | } | ||
43 | } | ||
44 | |||
45 | impl<LOC, ID> Loc2IdMap<LOC, ID> | ||
46 | where | ||
47 | ID: NumericId, | ||
48 | LOC: Clone + Eq + Hash, | ||
49 | { | ||
50 | pub fn loc2id(&mut self, loc: &LOC) -> ID { | ||
51 | match self.loc2id.get(loc) { | ||
52 | Some(id) => return id.clone(), | ||
53 | None => (), | ||
54 | } | ||
55 | let id = self.loc2id.len(); | ||
56 | assert!(id < u32::max_value() as usize); | ||
57 | let id = ID::from_u32(id as u32); | ||
58 | self.loc2id.insert(loc.clone(), id.clone()); | ||
59 | self.id2loc.insert(id.clone(), loc.clone()); | ||
60 | id | ||
61 | } | ||
62 | |||
63 | pub fn id2loc(&self, id: ID) -> LOC { | ||
64 | self.id2loc[&id].clone() | ||
65 | } | ||
66 | } | ||
67 | |||
68 | pub(crate) trait NumericId: Clone + Eq + Hash { | ||
69 | fn from_u32(id: u32) -> Self; | ||
70 | fn to_u32(self) -> u32; | ||
71 | } | ||
72 | 8 | ||
73 | macro_rules! impl_numeric_id { | 9 | macro_rules! impl_numeric_id { |
74 | ($id:ident) => { | 10 | ($id:ident) => { |
@@ -131,37 +67,3 @@ pub(crate) struct IdMaps { | |||
131 | pub(crate) fns: LocationIntener<SourceItemId, FnId>, | 67 | pub(crate) fns: LocationIntener<SourceItemId, FnId>, |
132 | pub(crate) defs: LocationIntener<DefLoc, DefId>, | 68 | pub(crate) defs: LocationIntener<DefLoc, DefId>, |
133 | } | 69 | } |
134 | |||
135 | #[derive(Debug)] | ||
136 | pub(crate) struct LocationIntener<LOC, ID> | ||
137 | where | ||
138 | ID: NumericId, | ||
139 | LOC: Clone + Eq + Hash, | ||
140 | { | ||
141 | map: Mutex<Loc2IdMap<LOC, ID>>, | ||
142 | } | ||
143 | |||
144 | impl<LOC, ID> Default for LocationIntener<LOC, ID> | ||
145 | where | ||
146 | ID: NumericId, | ||
147 | LOC: Clone + Eq + Hash, | ||
148 | { | ||
149 | fn default() -> Self { | ||
150 | LocationIntener { | ||
151 | map: Default::default(), | ||
152 | } | ||
153 | } | ||
154 | } | ||
155 | |||
156 | impl<LOC, ID> LocationIntener<LOC, ID> | ||
157 | where | ||
158 | ID: NumericId, | ||
159 | LOC: Clone + Eq + Hash, | ||
160 | { | ||
161 | fn loc2id(&self, loc: &LOC) -> ID { | ||
162 | self.map.lock().loc2id(loc) | ||
163 | } | ||
164 | fn id2loc(&self, id: ID) -> LOC { | ||
165 | self.map.lock().id2loc(id) | ||
166 | } | ||
167 | } | ||
diff --git a/crates/ra_analysis/src/symbol_index.rs b/crates/ra_analysis/src/symbol_index.rs index 747b34e38..b48a37229 100644 --- a/crates/ra_analysis/src/symbol_index.rs +++ b/crates/ra_analysis/src/symbol_index.rs | |||
@@ -9,13 +9,12 @@ use ra_syntax::{ | |||
9 | SourceFileNode, | 9 | SourceFileNode, |
10 | SyntaxKind::{self, *}, | 10 | SyntaxKind::{self, *}, |
11 | }; | 11 | }; |
12 | use ra_db::{SyntaxDatabase, SourceRootId}; | ||
12 | use rayon::prelude::*; | 13 | use rayon::prelude::*; |
13 | 14 | ||
14 | use crate::{ | 15 | use crate::{ |
15 | Cancelable, | 16 | Cancelable, |
16 | FileId, Query, | 17 | FileId, Query, |
17 | db::SyntaxDatabase, | ||
18 | input::SourceRootId, | ||
19 | }; | 18 | }; |
20 | 19 | ||
21 | salsa::query_group! { | 20 | salsa::query_group! { |
diff --git a/crates/ra_analysis/tests/tests.rs b/crates/ra_analysis/tests/tests.rs index 8e7856027..fbe89f444 100644 --- a/crates/ra_analysis/tests/tests.rs +++ b/crates/ra_analysis/tests/tests.rs | |||
@@ -126,7 +126,7 @@ fn test_resolve_crate_root() { | |||
126 | let mut host = mock.analysis_host(); | 126 | let mut host = mock.analysis_host(); |
127 | assert!(host.analysis().crate_for(mod_file).unwrap().is_empty()); | 127 | assert!(host.analysis().crate_for(mod_file).unwrap().is_empty()); |
128 | 128 | ||
129 | let mut crate_graph = CrateGraph::new(); | 129 | let mut crate_graph = CrateGraph::default(); |
130 | let crate_id = crate_graph.add_crate_root(root_file); | 130 | let crate_id = crate_graph.add_crate_root(root_file); |
131 | let mut change = AnalysisChange::new(); | 131 | let mut change = AnalysisChange::new(); |
132 | change.set_crate_graph(crate_graph); | 132 | change.set_crate_graph(crate_graph); |
diff --git a/crates/ra_db/Cargo.toml b/crates/ra_db/Cargo.toml new file mode 100644 index 000000000..3bf2f635e --- /dev/null +++ b/crates/ra_db/Cargo.toml | |||
@@ -0,0 +1,16 @@ | |||
1 | [package] | ||
2 | edition = "2018" | ||
3 | name = "ra_db" | ||
4 | version = "0.1.0" | ||
5 | authors = ["Aleksey Kladov <[email protected]>"] | ||
6 | |||
7 | [dependencies] | ||
8 | log = "0.4.5" | ||
9 | relative-path = "0.4.0" | ||
10 | salsa = "0.8.0" | ||
11 | rustc-hash = "1.0" | ||
12 | parking_lot = "0.6.4" | ||
13 | id-arena = { git = "https://github.com/fitzgen/id-arena/", rev = "43ecd67" } | ||
14 | ra_syntax = { path = "../ra_syntax" } | ||
15 | ra_editor = { path = "../ra_editor" } | ||
16 | test_utils = { path = "../test_utils" } | ||
diff --git a/crates/ra_db/src/file_resolver.rs b/crates/ra_db/src/file_resolver.rs new file mode 100644 index 000000000..f849ac752 --- /dev/null +++ b/crates/ra_db/src/file_resolver.rs | |||
@@ -0,0 +1,76 @@ | |||
1 | use std::{ | ||
2 | sync::Arc, | ||
3 | hash::{Hash, Hasher}, | ||
4 | fmt, | ||
5 | }; | ||
6 | |||
7 | use relative_path::RelativePath; | ||
8 | |||
9 | use crate::input::FileId; | ||
10 | |||
11 | pub trait FileResolver: fmt::Debug + Send + Sync + 'static { | ||
12 | fn file_stem(&self, file_id: FileId) -> String; | ||
13 | fn resolve(&self, file_id: FileId, path: &RelativePath) -> Option<FileId>; | ||
14 | fn debug_path(&self, _1file_id: FileId) -> Option<std::path::PathBuf> { | ||
15 | None | ||
16 | } | ||
17 | } | ||
18 | |||
19 | #[derive(Clone, Debug)] | ||
20 | pub struct FileResolverImp { | ||
21 | inner: Arc<FileResolver>, | ||
22 | } | ||
23 | |||
24 | impl PartialEq for FileResolverImp { | ||
25 | fn eq(&self, other: &FileResolverImp) -> bool { | ||
26 | self.inner() == other.inner() | ||
27 | } | ||
28 | } | ||
29 | |||
30 | impl Eq for FileResolverImp {} | ||
31 | |||
32 | impl Hash for FileResolverImp { | ||
33 | fn hash<H: Hasher>(&self, hasher: &mut H) { | ||
34 | self.inner().hash(hasher); | ||
35 | } | ||
36 | } | ||
37 | |||
38 | impl FileResolverImp { | ||
39 | pub fn new(inner: Arc<FileResolver>) -> FileResolverImp { | ||
40 | FileResolverImp { inner } | ||
41 | } | ||
42 | pub fn file_stem(&self, file_id: FileId) -> String { | ||
43 | self.inner.file_stem(file_id) | ||
44 | } | ||
45 | pub fn resolve(&self, file_id: FileId, path: &RelativePath) -> Option<FileId> { | ||
46 | self.inner.resolve(file_id, path) | ||
47 | } | ||
48 | pub fn debug_path(&self, file_id: FileId) -> Option<std::path::PathBuf> { | ||
49 | self.inner.debug_path(file_id) | ||
50 | } | ||
51 | fn inner(&self) -> *const FileResolver { | ||
52 | &*self.inner | ||
53 | } | ||
54 | } | ||
55 | |||
56 | impl Default for FileResolverImp { | ||
57 | fn default() -> FileResolverImp { | ||
58 | #[derive(Debug)] | ||
59 | struct DummyResolver; | ||
60 | impl FileResolver for DummyResolver { | ||
61 | fn file_stem(&self, _file_: FileId) -> String { | ||
62 | panic!("file resolver not set") | ||
63 | } | ||
64 | fn resolve( | ||
65 | &self, | ||
66 | _file_id: FileId, | ||
67 | _path: &::relative_path::RelativePath, | ||
68 | ) -> Option<FileId> { | ||
69 | panic!("file resolver not set") | ||
70 | } | ||
71 | } | ||
72 | FileResolverImp { | ||
73 | inner: Arc::new(DummyResolver), | ||
74 | } | ||
75 | } | ||
76 | } | ||
diff --git a/crates/ra_analysis/src/input.rs b/crates/ra_db/src/input.rs index e601cd58a..9101ac7a8 100644 --- a/crates/ra_analysis/src/input.rs +++ b/crates/ra_db/src/input.rs | |||
@@ -1,11 +1,10 @@ | |||
1 | use std::{fmt, sync::Arc}; | 1 | use std::sync::Arc; |
2 | 2 | ||
3 | use relative_path::RelativePath; | ||
4 | use rustc_hash::FxHashMap; | 3 | use rustc_hash::FxHashMap; |
5 | use rustc_hash::FxHashSet; | 4 | use rustc_hash::FxHashSet; |
6 | use salsa; | 5 | use salsa; |
7 | 6 | ||
8 | use crate::FileResolverImp; | 7 | use crate::file_resolver::FileResolverImp; |
9 | 8 | ||
10 | #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] | 9 | #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] |
11 | pub struct FileId(pub u32); | 10 | pub struct FileId(pub u32); |
@@ -19,8 +18,8 @@ pub struct CrateGraph { | |||
19 | } | 18 | } |
20 | 19 | ||
21 | impl CrateGraph { | 20 | impl CrateGraph { |
22 | pub fn new() -> CrateGraph { | 21 | pub fn crate_root(&self, crate_id: CrateId) -> FileId { |
23 | CrateGraph::default() | 22 | self.crate_roots[&crate_id] |
24 | } | 23 | } |
25 | pub fn add_crate_root(&mut self, file_id: FileId) -> CrateId { | 24 | pub fn add_crate_root(&mut self, file_id: FileId) -> CrateId { |
26 | let crate_id = CrateId(self.crate_roots.len() as u32); | 25 | let crate_id = CrateId(self.crate_roots.len() as u32); |
@@ -28,18 +27,17 @@ impl CrateGraph { | |||
28 | assert!(prev.is_none()); | 27 | assert!(prev.is_none()); |
29 | crate_id | 28 | crate_id |
30 | } | 29 | } |
31 | } | 30 | pub fn crate_id_for_crate_root(&self, file_id: FileId) -> Option<CrateId> { |
32 | 31 | let (&crate_id, _) = self | |
33 | pub trait FileResolver: fmt::Debug + Send + Sync + 'static { | 32 | .crate_roots |
34 | fn file_stem(&self, file_id: FileId) -> String; | 33 | .iter() |
35 | fn resolve(&self, file_id: FileId, path: &RelativePath) -> Option<FileId>; | 34 | .find(|(_crate_id, &root_id)| root_id == file_id)?; |
36 | fn debug_path(&self, _1file_id: FileId) -> Option<std::path::PathBuf> { | 35 | Some(crate_id) |
37 | None | ||
38 | } | 36 | } |
39 | } | 37 | } |
40 | 38 | ||
41 | salsa::query_group! { | 39 | salsa::query_group! { |
42 | pub(crate) trait FilesDatabase: salsa::Database { | 40 | pub trait FilesDatabase: salsa::Database { |
43 | fn file_text(file_id: FileId) -> Arc<String> { | 41 | fn file_text(file_id: FileId) -> Arc<String> { |
44 | type FileTextQuery; | 42 | type FileTextQuery; |
45 | storage input; | 43 | storage input; |
@@ -64,12 +62,12 @@ salsa::query_group! { | |||
64 | } | 62 | } |
65 | 63 | ||
66 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)] | 64 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)] |
67 | pub(crate) struct SourceRootId(pub(crate) u32); | 65 | pub struct SourceRootId(pub u32); |
68 | 66 | ||
69 | #[derive(Default, Clone, Debug, PartialEq, Eq)] | 67 | #[derive(Default, Clone, Debug, PartialEq, Eq)] |
70 | pub(crate) struct SourceRoot { | 68 | pub struct SourceRoot { |
71 | pub(crate) file_resolver: FileResolverImp, | 69 | pub file_resolver: FileResolverImp, |
72 | pub(crate) files: FxHashSet<FileId>, | 70 | pub files: FxHashSet<FileId>, |
73 | } | 71 | } |
74 | 72 | ||
75 | pub(crate) const WORKSPACE: SourceRootId = SourceRootId(0); | 73 | pub const WORKSPACE: SourceRootId = SourceRootId(0); |
diff --git a/crates/ra_db/src/lib.rs b/crates/ra_db/src/lib.rs new file mode 100644 index 000000000..833f95eeb --- /dev/null +++ b/crates/ra_db/src/lib.rs | |||
@@ -0,0 +1,69 @@ | |||
1 | //! ra_db defines basic database traits. Concrete DB is defined by ra_analysis. | ||
2 | |||
3 | extern crate ra_editor; | ||
4 | extern crate ra_syntax; | ||
5 | extern crate relative_path; | ||
6 | extern crate rustc_hash; | ||
7 | extern crate salsa; | ||
8 | |||
9 | mod syntax_ptr; | ||
10 | mod file_resolver; | ||
11 | mod input; | ||
12 | mod loc2id; | ||
13 | |||
14 | use std::sync::Arc; | ||
15 | use ra_editor::LineIndex; | ||
16 | use ra_syntax::SourceFileNode; | ||
17 | |||
18 | #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)] | ||
19 | pub struct Canceled; | ||
20 | |||
21 | pub type Cancelable<T> = Result<T, Canceled>; | ||
22 | |||
23 | impl std::fmt::Display for Canceled { | ||
24 | fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | ||
25 | fmt.write_str("Canceled") | ||
26 | } | ||
27 | } | ||
28 | |||
29 | impl std::error::Error for Canceled {} | ||
30 | |||
31 | pub use crate::{ | ||
32 | syntax_ptr::LocalSyntaxPtr, | ||
33 | file_resolver::{FileResolver, FileResolverImp}, | ||
34 | input::{ | ||
35 | FilesDatabase, FileId, CrateId, SourceRoot, SourceRootId, CrateGraph, WORKSPACE, | ||
36 | FileTextQuery, FileSourceRootQuery, SourceRootQuery, LibrariesQuery, CrateGraphQuery, | ||
37 | }, | ||
38 | loc2id::{LocationIntener, NumericId}, | ||
39 | }; | ||
40 | |||
41 | pub trait BaseDatabase: salsa::Database { | ||
42 | fn check_canceled(&self) -> Cancelable<()> { | ||
43 | if self.salsa_runtime().is_current_revision_canceled() { | ||
44 | Err(Canceled) | ||
45 | } else { | ||
46 | Ok(()) | ||
47 | } | ||
48 | } | ||
49 | } | ||
50 | |||
51 | salsa::query_group! { | ||
52 | pub trait SyntaxDatabase: crate::input::FilesDatabase + BaseDatabase { | ||
53 | fn source_file(file_id: FileId) -> SourceFileNode { | ||
54 | type SourceFileQuery; | ||
55 | } | ||
56 | fn file_lines(file_id: FileId) -> Arc<LineIndex> { | ||
57 | type FileLinesQuery; | ||
58 | } | ||
59 | } | ||
60 | } | ||
61 | |||
62 | fn source_file(db: &impl SyntaxDatabase, file_id: FileId) -> SourceFileNode { | ||
63 | let text = db.file_text(file_id); | ||
64 | SourceFileNode::parse(&*text) | ||
65 | } | ||
66 | fn file_lines(db: &impl SyntaxDatabase, file_id: FileId) -> Arc<LineIndex> { | ||
67 | let text = db.file_text(file_id); | ||
68 | Arc::new(LineIndex::new(&*text)) | ||
69 | } | ||
diff --git a/crates/ra_db/src/loc2id.rs b/crates/ra_db/src/loc2id.rs new file mode 100644 index 000000000..69ba43d0f --- /dev/null +++ b/crates/ra_db/src/loc2id.rs | |||
@@ -0,0 +1,100 @@ | |||
1 | use parking_lot::Mutex; | ||
2 | |||
3 | use std::hash::Hash; | ||
4 | |||
5 | use rustc_hash::FxHashMap; | ||
6 | |||
7 | /// There are two principle ways to refer to things: | ||
8 | /// - by their locatinon (module in foo/bar/baz.rs at line 42) | ||
9 | /// - by their numeric id (module `ModuleId(42)`) | ||
10 | /// | ||
11 | /// The first one is more powerful (you can actually find the thing in question | ||
12 | /// by id), but the second one is so much more compact. | ||
13 | /// | ||
14 | /// `Loc2IdMap` allows us to have a cake an eat it as well: by maintaining a | ||
15 | /// bidirectional mapping between positional and numeric ids, we can use compact | ||
16 | /// representation wich still allows us to get the actual item | ||
17 | #[derive(Debug)] | ||
18 | struct Loc2IdMap<LOC, ID> | ||
19 | where | ||
20 | ID: NumericId, | ||
21 | LOC: Clone + Eq + Hash, | ||
22 | { | ||
23 | loc2id: FxHashMap<LOC, ID>, | ||
24 | id2loc: FxHashMap<ID, LOC>, | ||
25 | } | ||
26 | |||
27 | impl<LOC, ID> Default for Loc2IdMap<LOC, ID> | ||
28 | where | ||
29 | ID: NumericId, | ||
30 | LOC: Clone + Eq + Hash, | ||
31 | { | ||
32 | fn default() -> Self { | ||
33 | Loc2IdMap { | ||
34 | loc2id: FxHashMap::default(), | ||
35 | id2loc: FxHashMap::default(), | ||
36 | } | ||
37 | } | ||
38 | } | ||
39 | |||
40 | impl<LOC, ID> Loc2IdMap<LOC, ID> | ||
41 | where | ||
42 | ID: NumericId, | ||
43 | LOC: Clone + Eq + Hash, | ||
44 | { | ||
45 | pub fn loc2id(&mut self, loc: &LOC) -> ID { | ||
46 | match self.loc2id.get(loc) { | ||
47 | Some(id) => return id.clone(), | ||
48 | None => (), | ||
49 | } | ||
50 | let id = self.loc2id.len(); | ||
51 | assert!(id < u32::max_value() as usize); | ||
52 | let id = ID::from_u32(id as u32); | ||
53 | self.loc2id.insert(loc.clone(), id.clone()); | ||
54 | self.id2loc.insert(id.clone(), loc.clone()); | ||
55 | id | ||
56 | } | ||
57 | |||
58 | pub fn id2loc(&self, id: ID) -> LOC { | ||
59 | self.id2loc[&id].clone() | ||
60 | } | ||
61 | } | ||
62 | |||
63 | pub trait NumericId: Clone + Eq + Hash { | ||
64 | fn from_u32(id: u32) -> Self; | ||
65 | fn to_u32(self) -> u32; | ||
66 | } | ||
67 | |||
68 | #[derive(Debug)] | ||
69 | pub struct LocationIntener<LOC, ID> | ||
70 | where | ||
71 | ID: NumericId, | ||
72 | LOC: Clone + Eq + Hash, | ||
73 | { | ||
74 | map: Mutex<Loc2IdMap<LOC, ID>>, | ||
75 | } | ||
76 | |||
77 | impl<LOC, ID> Default for LocationIntener<LOC, ID> | ||
78 | where | ||
79 | ID: NumericId, | ||
80 | LOC: Clone + Eq + Hash, | ||
81 | { | ||
82 | fn default() -> Self { | ||
83 | LocationIntener { | ||
84 | map: Default::default(), | ||
85 | } | ||
86 | } | ||
87 | } | ||
88 | |||
89 | impl<LOC, ID> LocationIntener<LOC, ID> | ||
90 | where | ||
91 | ID: NumericId, | ||
92 | LOC: Clone + Eq + Hash, | ||
93 | { | ||
94 | pub fn loc2id(&self, loc: &LOC) -> ID { | ||
95 | self.map.lock().loc2id(loc) | ||
96 | } | ||
97 | pub fn id2loc(&self, id: ID) -> LOC { | ||
98 | self.map.lock().id2loc(id) | ||
99 | } | ||
100 | } | ||
diff --git a/crates/ra_analysis/src/syntax_ptr.rs b/crates/ra_db/src/syntax_ptr.rs index f4b05fc19..dac94dd36 100644 --- a/crates/ra_analysis/src/syntax_ptr.rs +++ b/crates/ra_db/src/syntax_ptr.rs | |||
@@ -2,20 +2,20 @@ use ra_syntax::{SourceFileNode, SyntaxKind, SyntaxNode, SyntaxNodeRef, TextRange | |||
2 | 2 | ||
3 | /// A pionter to a syntax node inside a file. | 3 | /// A pionter to a syntax node inside a file. |
4 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | 4 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] |
5 | pub(crate) struct LocalSyntaxPtr { | 5 | pub struct LocalSyntaxPtr { |
6 | range: TextRange, | 6 | range: TextRange, |
7 | kind: SyntaxKind, | 7 | kind: SyntaxKind, |
8 | } | 8 | } |
9 | 9 | ||
10 | impl LocalSyntaxPtr { | 10 | impl LocalSyntaxPtr { |
11 | pub(crate) fn new(node: SyntaxNodeRef) -> LocalSyntaxPtr { | 11 | pub fn new(node: SyntaxNodeRef) -> LocalSyntaxPtr { |
12 | LocalSyntaxPtr { | 12 | LocalSyntaxPtr { |
13 | range: node.range(), | 13 | range: node.range(), |
14 | kind: node.kind(), | 14 | kind: node.kind(), |
15 | } | 15 | } |
16 | } | 16 | } |
17 | 17 | ||
18 | pub(crate) fn resolve(self, file: &SourceFileNode) -> SyntaxNode { | 18 | pub fn resolve(self, file: &SourceFileNode) -> SyntaxNode { |
19 | let mut curr = file.syntax(); | 19 | let mut curr = file.syntax(); |
20 | loop { | 20 | loop { |
21 | if curr.range() == self.range && curr.kind() == self.kind { | 21 | if curr.range() == self.range && curr.kind() == self.kind { |
@@ -28,7 +28,7 @@ impl LocalSyntaxPtr { | |||
28 | } | 28 | } |
29 | } | 29 | } |
30 | 30 | ||
31 | pub(crate) fn range(self) -> TextRange { | 31 | pub fn range(self) -> TextRange { |
32 | self.range | 32 | self.range |
33 | } | 33 | } |
34 | } | 34 | } |
diff --git a/crates/ra_lsp_server/src/server_world.rs b/crates/ra_lsp_server/src/server_world.rs index 3e7670fcc..12faeb93a 100644 --- a/crates/ra_lsp_server/src/server_world.rs +++ b/crates/ra_lsp_server/src/server_world.rs | |||
@@ -140,7 +140,7 @@ impl ServerWorldState { | |||
140 | Ok(file_id) | 140 | Ok(file_id) |
141 | } | 141 | } |
142 | pub fn set_workspaces(&mut self, ws: Vec<CargoWorkspace>) { | 142 | pub fn set_workspaces(&mut self, ws: Vec<CargoWorkspace>) { |
143 | let mut crate_graph = CrateGraph::new(); | 143 | let mut crate_graph = CrateGraph::default(); |
144 | ws.iter() | 144 | ws.iter() |
145 | .flat_map(|ws| { | 145 | .flat_map(|ws| { |
146 | ws.packages() | 146 | ws.packages() |