aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_db
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_db')
-rw-r--r--crates/ra_db/Cargo.toml2
-rw-r--r--crates/ra_db/src/fixture.rs32
-rw-r--r--crates/ra_db/src/input.rs79
-rw-r--r--crates/ra_db/src/lib.rs28
4 files changed, 31 insertions, 110 deletions
diff --git a/crates/ra_db/Cargo.toml b/crates/ra_db/Cargo.toml
index 8ab409158..372fb242b 100644
--- a/crates/ra_db/Cargo.toml
+++ b/crates/ra_db/Cargo.toml
@@ -17,3 +17,5 @@ ra_cfg = { path = "../ra_cfg" }
17ra_prof = { path = "../ra_prof" } 17ra_prof = { path = "../ra_prof" }
18ra_tt = { path = "../ra_tt" } 18ra_tt = { path = "../ra_tt" }
19test_utils = { path = "../test_utils" } 19test_utils = { path = "../test_utils" }
20vfs = { path = "../vfs" }
21stdx = { path = "../stdx" }
diff --git a/crates/ra_db/src/fixture.rs b/crates/ra_db/src/fixture.rs
index af8fe11ec..f7d9118a9 100644
--- a/crates/ra_db/src/fixture.rs
+++ b/crates/ra_db/src/fixture.rs
@@ -57,17 +57,16 @@
57//! fn insert_source_code_here() {} 57//! fn insert_source_code_here() {}
58//! " 58//! "
59//! ``` 59//! ```
60 60use std::{str::FromStr, sync::Arc};
61use std::str::FromStr;
62use std::sync::Arc;
63 61
64use ra_cfg::CfgOptions; 62use ra_cfg::CfgOptions;
65use rustc_hash::FxHashMap; 63use rustc_hash::FxHashMap;
66use test_utils::{extract_offset, parse_fixture, parse_single_fixture, FixtureMeta, CURSOR_MARKER}; 64use test_utils::{extract_offset, parse_fixture, parse_single_fixture, FixtureMeta, CURSOR_MARKER};
65use vfs::{file_set::FileSet, VfsPath};
67 66
68use crate::{ 67use crate::{
69 input::CrateName, CrateGraph, CrateId, Edition, Env, FileId, FilePosition, RelativePathBuf, 68 input::CrateName, CrateGraph, CrateId, Edition, Env, FileId, FilePosition, SourceDatabaseExt,
70 SourceDatabaseExt, SourceRoot, SourceRootId, 69 SourceRoot, SourceRootId,
71}; 70};
72 71
73pub const WORKSPACE: SourceRootId = SourceRootId(0); 72pub const WORKSPACE: SourceRootId = SourceRootId(0);
@@ -105,10 +104,10 @@ impl<DB: SourceDatabaseExt + Default + 'static> WithFixture for DB {}
105 104
106fn with_single_file(db: &mut dyn SourceDatabaseExt, ra_fixture: &str) -> FileId { 105fn with_single_file(db: &mut dyn SourceDatabaseExt, ra_fixture: &str) -> FileId {
107 let file_id = FileId(0); 106 let file_id = FileId(0);
108 let rel_path: RelativePathBuf = "/main.rs".into(); 107 let mut file_set = vfs::file_set::FileSet::default();
108 file_set.insert(file_id, vfs::VfsPath::new_virtual_path("/main.rs".to_string()));
109 109
110 let mut source_root = SourceRoot::new_local(); 110 let source_root = SourceRoot::new_local(file_set);
111 source_root.insert_file(rel_path.clone(), file_id);
112 111
113 let fixture = parse_single_fixture(ra_fixture); 112 let fixture = parse_single_fixture(ra_fixture);
114 113
@@ -128,7 +127,6 @@ fn with_single_file(db: &mut dyn SourceDatabaseExt, ra_fixture: &str) -> FileId
128 meta.cfg, 127 meta.cfg,
129 meta.env, 128 meta.env,
130 Default::default(), 129 Default::default(),
131 Default::default(),
132 ); 130 );
133 crate_graph 131 crate_graph
134 } else { 132 } else {
@@ -140,13 +138,11 @@ fn with_single_file(db: &mut dyn SourceDatabaseExt, ra_fixture: &str) -> FileId
140 CfgOptions::default(), 138 CfgOptions::default(),
141 Env::default(), 139 Env::default(),
142 Default::default(), 140 Default::default(),
143 Default::default(),
144 ); 141 );
145 crate_graph 142 crate_graph
146 }; 143 };
147 144
148 db.set_file_text(file_id, Arc::new(ra_fixture.to_string())); 145 db.set_file_text(file_id, Arc::new(ra_fixture.to_string()));
149 db.set_file_relative_path(file_id, rel_path);
150 db.set_file_source_root(file_id, WORKSPACE); 146 db.set_file_source_root(file_id, WORKSPACE);
151 db.set_source_root(WORKSPACE, Arc::new(source_root)); 147 db.set_source_root(WORKSPACE, Arc::new(source_root));
152 db.set_crate_graph(Arc::new(crate_graph)); 148 db.set_crate_graph(Arc::new(crate_graph));
@@ -162,7 +158,7 @@ fn with_files(db: &mut dyn SourceDatabaseExt, fixture: &str) -> Option<FilePosit
162 let mut crate_deps = Vec::new(); 158 let mut crate_deps = Vec::new();
163 let mut default_crate_root: Option<FileId> = None; 159 let mut default_crate_root: Option<FileId> = None;
164 160
165 let mut source_root = SourceRoot::new_local(); 161 let mut file_set = FileSet::default();
166 let mut source_root_id = WORKSPACE; 162 let mut source_root_id = WORKSPACE;
167 let mut source_root_prefix = "/".to_string(); 163 let mut source_root_prefix = "/".to_string();
168 let mut file_id = FileId(0); 164 let mut file_id = FileId(0);
@@ -172,8 +168,8 @@ fn with_files(db: &mut dyn SourceDatabaseExt, fixture: &str) -> Option<FilePosit
172 for entry in fixture.iter() { 168 for entry in fixture.iter() {
173 let meta = match ParsedMeta::from(&entry.meta) { 169 let meta = match ParsedMeta::from(&entry.meta) {
174 ParsedMeta::Root { path } => { 170 ParsedMeta::Root { path } => {
175 let source_root = std::mem::replace(&mut source_root, SourceRoot::new_local()); 171 let file_set = std::mem::replace(&mut file_set, FileSet::default());
176 db.set_source_root(source_root_id, Arc::new(source_root)); 172 db.set_source_root(source_root_id, Arc::new(SourceRoot::new_local(file_set)));
177 source_root_id.0 += 1; 173 source_root_id.0 += 1;
178 source_root_prefix = path; 174 source_root_prefix = path;
179 continue; 175 continue;
@@ -190,7 +186,6 @@ fn with_files(db: &mut dyn SourceDatabaseExt, fixture: &str) -> Option<FilePosit
190 meta.cfg, 186 meta.cfg,
191 meta.env, 187 meta.env,
192 Default::default(), 188 Default::default(),
193 Default::default(),
194 ); 189 );
195 let prev = crates.insert(krate.clone(), crate_id); 190 let prev = crates.insert(krate.clone(), crate_id);
196 assert!(prev.is_none()); 191 assert!(prev.is_none());
@@ -212,9 +207,9 @@ fn with_files(db: &mut dyn SourceDatabaseExt, fixture: &str) -> Option<FilePosit
212 }; 207 };
213 208
214 db.set_file_text(file_id, Arc::new(text)); 209 db.set_file_text(file_id, Arc::new(text));
215 db.set_file_relative_path(file_id, meta.path.clone().into());
216 db.set_file_source_root(file_id, source_root_id); 210 db.set_file_source_root(file_id, source_root_id);
217 source_root.insert_file(meta.path.into(), file_id); 211 let path = VfsPath::new_virtual_path(meta.path);
212 file_set.insert(file_id, path.into());
218 213
219 file_id.0 += 1; 214 file_id.0 += 1;
220 } 215 }
@@ -228,7 +223,6 @@ fn with_files(db: &mut dyn SourceDatabaseExt, fixture: &str) -> Option<FilePosit
228 CfgOptions::default(), 223 CfgOptions::default(),
229 Env::default(), 224 Env::default(),
230 Default::default(), 225 Default::default(),
231 Default::default(),
232 ); 226 );
233 } else { 227 } else {
234 for (from, to) in crate_deps { 228 for (from, to) in crate_deps {
@@ -238,7 +232,7 @@ fn with_files(db: &mut dyn SourceDatabaseExt, fixture: &str) -> Option<FilePosit
238 } 232 }
239 } 233 }
240 234
241 db.set_source_root(source_root_id, Arc::new(source_root)); 235 db.set_source_root(source_root_id, Arc::new(SourceRoot::new_local(file_set)));
242 db.set_crate_graph(Arc::new(crate_graph)); 236 db.set_crate_graph(Arc::new(crate_graph));
243 237
244 file_position 238 file_position
diff --git a/crates/ra_db/src/input.rs b/crates/ra_db/src/input.rs
index e6af99035..7f3660118 100644
--- a/crates/ra_db/src/input.rs
+++ b/crates/ra_db/src/input.rs
@@ -6,27 +6,15 @@
6//! actual IO. See `vfs` and `project_model` in the `rust-analyzer` crate for how 6//! actual IO. See `vfs` and `project_model` in the `rust-analyzer` crate for how
7//! actual IO is done and lowered to input. 7//! actual IO is done and lowered to input.
8 8
9use std::{ 9use std::{fmt, ops, str::FromStr, sync::Arc};
10 fmt, ops,
11 path::{Path, PathBuf},
12 str::FromStr,
13 sync::Arc,
14};
15 10
16use ra_cfg::CfgOptions; 11use ra_cfg::CfgOptions;
17use ra_syntax::SmolStr; 12use ra_syntax::SmolStr;
18use ra_tt::TokenExpander; 13use ra_tt::TokenExpander;
19use rustc_hash::{FxHashMap, FxHashSet}; 14use rustc_hash::{FxHashMap, FxHashSet};
15use vfs::file_set::FileSet;
20 16
21use crate::{RelativePath, RelativePathBuf}; 17pub use vfs::FileId;
22
23/// `FileId` is an integer which uniquely identifies a file. File paths are
24/// messy and system-dependent, so most of the code should work directly with
25/// `FileId`, without inspecting the path. The mapping between `FileId` and path
26/// and `SourceRoot` is constant. A file rename is represented as a pair of
27/// deletion/creation.
28#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
29pub struct FileId(pub u32);
30 18
31/// Files are grouped into source roots. A source root is a directory on the 19/// Files are grouped into source roots. A source root is a directory on the
32/// file systems which is watched for changes. Typically it corresponds to a 20/// file systems which is watched for changes. Typically it corresponds to a
@@ -45,27 +33,18 @@ pub struct SourceRoot {
45 /// Libraries are considered mostly immutable, this assumption is used to 33 /// Libraries are considered mostly immutable, this assumption is used to
46 /// optimize salsa's query structure 34 /// optimize salsa's query structure
47 pub is_library: bool, 35 pub is_library: bool,
48 files: FxHashMap<RelativePathBuf, FileId>, 36 pub(crate) file_set: FileSet,
49} 37}
50 38
51impl SourceRoot { 39impl SourceRoot {
52 pub fn new_local() -> SourceRoot { 40 pub fn new_local(file_set: FileSet) -> SourceRoot {
53 SourceRoot { is_library: false, files: Default::default() } 41 SourceRoot { is_library: false, file_set }
54 }
55 pub fn new_library() -> SourceRoot {
56 SourceRoot { is_library: true, files: Default::default() }
57 }
58 pub fn insert_file(&mut self, path: RelativePathBuf, file_id: FileId) {
59 self.files.insert(path, file_id);
60 } 42 }
61 pub fn remove_file(&mut self, path: &RelativePath) { 43 pub fn new_library(file_set: FileSet) -> SourceRoot {
62 self.files.remove(path); 44 SourceRoot { is_library: true, file_set }
63 } 45 }
64 pub fn walk(&self) -> impl Iterator<Item = FileId> + '_ { 46 pub fn iter(&self) -> impl Iterator<Item = FileId> + '_ {
65 self.files.values().copied() 47 self.file_set.iter()
66 }
67 pub fn file_by_relative_path(&self, path: &RelativePath) -> Option<FileId> {
68 self.files.get(path).copied()
69 } 48 }
70} 49}
71 50
@@ -141,7 +120,6 @@ pub struct CrateData {
141 pub display_name: Option<CrateName>, 120 pub display_name: Option<CrateName>,
142 pub cfg_options: CfgOptions, 121 pub cfg_options: CfgOptions,
143 pub env: Env, 122 pub env: Env,
144 pub extern_source: ExternSource,
145 pub dependencies: Vec<Dependency>, 123 pub dependencies: Vec<Dependency>,
146 pub proc_macro: Vec<ProcMacro>, 124 pub proc_macro: Vec<ProcMacro>,
147} 125}
@@ -152,22 +130,11 @@ pub enum Edition {
152 Edition2015, 130 Edition2015,
153} 131}
154 132
155#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
156pub struct ExternSourceId(pub u32);
157
158#[derive(Default, Debug, Clone, PartialEq, Eq)] 133#[derive(Default, Debug, Clone, PartialEq, Eq)]
159pub struct Env { 134pub struct Env {
160 entries: FxHashMap<String, String>, 135 entries: FxHashMap<String, String>,
161} 136}
162 137
163// FIXME: Redesign vfs for solve the following limitation ?
164// Note: Some env variables (e.g. OUT_DIR) are located outside of the
165// crate. We store a map to allow remap it to ExternSourceId
166#[derive(Default, Debug, Clone, PartialEq, Eq)]
167pub struct ExternSource {
168 extern_paths: FxHashMap<PathBuf, ExternSourceId>,
169}
170
171#[derive(Debug, Clone, PartialEq, Eq)] 138#[derive(Debug, Clone, PartialEq, Eq)]
172pub struct Dependency { 139pub struct Dependency {
173 pub crate_id: CrateId, 140 pub crate_id: CrateId,
@@ -182,7 +149,6 @@ impl CrateGraph {
182 display_name: Option<CrateName>, 149 display_name: Option<CrateName>,
183 cfg_options: CfgOptions, 150 cfg_options: CfgOptions,
184 env: Env, 151 env: Env,
185 extern_source: ExternSource,
186 proc_macro: Vec<(SmolStr, Arc<dyn ra_tt::TokenExpander>)>, 152 proc_macro: Vec<(SmolStr, Arc<dyn ra_tt::TokenExpander>)>,
187 ) -> CrateId { 153 ) -> CrateId {
188 let proc_macro = 154 let proc_macro =
@@ -194,7 +160,6 @@ impl CrateGraph {
194 display_name, 160 display_name,
195 cfg_options, 161 cfg_options,
196 env, 162 env,
197 extern_source,
198 proc_macro, 163 proc_macro,
199 dependencies: Vec::new(), 164 dependencies: Vec::new(),
200 }; 165 };
@@ -334,20 +299,6 @@ impl Env {
334 } 299 }
335} 300}
336 301
337impl ExternSource {
338 pub fn extern_path(&self, path: &Path) -> Option<(ExternSourceId, RelativePathBuf)> {
339 self.extern_paths.iter().find_map(|(root_path, id)| {
340 let rel_path = path.strip_prefix(root_path).ok()?;
341 let rel_path = RelativePathBuf::from_path(rel_path).ok()?;
342 Some((*id, rel_path))
343 })
344 }
345
346 pub fn set_extern_path(&mut self, root_path: &Path, root: ExternSourceId) {
347 self.extern_paths.insert(root_path.to_path_buf(), root);
348 }
349}
350
351#[derive(Debug)] 302#[derive(Debug)]
352pub struct ParseEditionError { 303pub struct ParseEditionError {
353 invalid_input: String, 304 invalid_input: String,
@@ -378,7 +329,6 @@ mod tests {
378 CfgOptions::default(), 329 CfgOptions::default(),
379 Env::default(), 330 Env::default(),
380 Default::default(), 331 Default::default(),
381 Default::default(),
382 ); 332 );
383 let crate2 = graph.add_crate_root( 333 let crate2 = graph.add_crate_root(
384 FileId(2u32), 334 FileId(2u32),
@@ -387,7 +337,6 @@ mod tests {
387 CfgOptions::default(), 337 CfgOptions::default(),
388 Env::default(), 338 Env::default(),
389 Default::default(), 339 Default::default(),
390 Default::default(),
391 ); 340 );
392 let crate3 = graph.add_crate_root( 341 let crate3 = graph.add_crate_root(
393 FileId(3u32), 342 FileId(3u32),
@@ -396,7 +345,6 @@ mod tests {
396 CfgOptions::default(), 345 CfgOptions::default(),
397 Env::default(), 346 Env::default(),
398 Default::default(), 347 Default::default(),
399 Default::default(),
400 ); 348 );
401 assert!(graph.add_dep(crate1, CrateName::new("crate2").unwrap(), crate2).is_ok()); 349 assert!(graph.add_dep(crate1, CrateName::new("crate2").unwrap(), crate2).is_ok());
402 assert!(graph.add_dep(crate2, CrateName::new("crate3").unwrap(), crate3).is_ok()); 350 assert!(graph.add_dep(crate2, CrateName::new("crate3").unwrap(), crate3).is_ok());
@@ -413,7 +361,6 @@ mod tests {
413 CfgOptions::default(), 361 CfgOptions::default(),
414 Env::default(), 362 Env::default(),
415 Default::default(), 363 Default::default(),
416 Default::default(),
417 ); 364 );
418 let crate2 = graph.add_crate_root( 365 let crate2 = graph.add_crate_root(
419 FileId(2u32), 366 FileId(2u32),
@@ -422,7 +369,6 @@ mod tests {
422 CfgOptions::default(), 369 CfgOptions::default(),
423 Env::default(), 370 Env::default(),
424 Default::default(), 371 Default::default(),
425 Default::default(),
426 ); 372 );
427 assert!(graph.add_dep(crate1, CrateName::new("crate2").unwrap(), crate2).is_ok()); 373 assert!(graph.add_dep(crate1, CrateName::new("crate2").unwrap(), crate2).is_ok());
428 assert!(graph.add_dep(crate2, CrateName::new("crate2").unwrap(), crate2).is_err()); 374 assert!(graph.add_dep(crate2, CrateName::new("crate2").unwrap(), crate2).is_err());
@@ -438,7 +384,6 @@ mod tests {
438 CfgOptions::default(), 384 CfgOptions::default(),
439 Env::default(), 385 Env::default(),
440 Default::default(), 386 Default::default(),
441 Default::default(),
442 ); 387 );
443 let crate2 = graph.add_crate_root( 388 let crate2 = graph.add_crate_root(
444 FileId(2u32), 389 FileId(2u32),
@@ -447,7 +392,6 @@ mod tests {
447 CfgOptions::default(), 392 CfgOptions::default(),
448 Env::default(), 393 Env::default(),
449 Default::default(), 394 Default::default(),
450 Default::default(),
451 ); 395 );
452 let crate3 = graph.add_crate_root( 396 let crate3 = graph.add_crate_root(
453 FileId(3u32), 397 FileId(3u32),
@@ -456,7 +400,6 @@ mod tests {
456 CfgOptions::default(), 400 CfgOptions::default(),
457 Env::default(), 401 Env::default(),
458 Default::default(), 402 Default::default(),
459 Default::default(),
460 ); 403 );
461 assert!(graph.add_dep(crate1, CrateName::new("crate2").unwrap(), crate2).is_ok()); 404 assert!(graph.add_dep(crate1, CrateName::new("crate2").unwrap(), crate2).is_ok());
462 assert!(graph.add_dep(crate2, CrateName::new("crate3").unwrap(), crate3).is_ok()); 405 assert!(graph.add_dep(crate2, CrateName::new("crate3").unwrap(), crate3).is_ok());
@@ -472,7 +415,6 @@ mod tests {
472 CfgOptions::default(), 415 CfgOptions::default(),
473 Env::default(), 416 Env::default(),
474 Default::default(), 417 Default::default(),
475 Default::default(),
476 ); 418 );
477 let crate2 = graph.add_crate_root( 419 let crate2 = graph.add_crate_root(
478 FileId(2u32), 420 FileId(2u32),
@@ -481,7 +423,6 @@ mod tests {
481 CfgOptions::default(), 423 CfgOptions::default(),
482 Env::default(), 424 Env::default(),
483 Default::default(), 425 Default::default(),
484 Default::default(),
485 ); 426 );
486 assert!(graph 427 assert!(graph
487 .add_dep(crate1, CrateName::normalize_dashes("crate-name-with-dashes"), crate2) 428 .add_dep(crate1, CrateName::normalize_dashes("crate-name-with-dashes"), crate2)
diff --git a/crates/ra_db/src/lib.rs b/crates/ra_db/src/lib.rs
index 80ddb6058..875290259 100644
--- a/crates/ra_db/src/lib.rs
+++ b/crates/ra_db/src/lib.rs
@@ -12,12 +12,13 @@ use rustc_hash::FxHashSet;
12pub use crate::{ 12pub use crate::{
13 cancellation::Canceled, 13 cancellation::Canceled,
14 input::{ 14 input::{
15 CrateData, CrateGraph, CrateId, CrateName, Dependency, Edition, Env, ExternSource, 15 CrateData, CrateGraph, CrateId, CrateName, Dependency, Edition, Env, FileId, ProcMacroId,
16 ExternSourceId, FileId, ProcMacroId, SourceRoot, SourceRootId, 16 SourceRoot, SourceRootId,
17 }, 17 },
18}; 18};
19pub use relative_path::{RelativePath, RelativePathBuf}; 19pub use relative_path::{RelativePath, RelativePathBuf};
20pub use salsa; 20pub use salsa;
21pub use vfs::{file_set::FileSet, AbsPathBuf, VfsPath};
21 22
22#[macro_export] 23#[macro_export]
23macro_rules! impl_intern_key { 24macro_rules! impl_intern_key {
@@ -125,8 +126,6 @@ pub trait SourceDatabaseExt: SourceDatabase {
125 #[salsa::input] 126 #[salsa::input]
126 fn file_text(&self, file_id: FileId) -> Arc<String>; 127 fn file_text(&self, file_id: FileId) -> Arc<String>;
127 /// Path to a file, relative to the root of its source root. 128 /// Path to a file, relative to the root of its source root.
128 #[salsa::input]
129 fn file_relative_path(&self, file_id: FileId) -> RelativePathBuf;
130 /// Source root of the file. 129 /// Source root of the file.
131 #[salsa::input] 130 #[salsa::input]
132 fn file_source_root(&self, file_id: FileId) -> SourceRootId; 131 fn file_source_root(&self, file_id: FileId) -> SourceRootId;
@@ -161,24 +160,9 @@ impl<T: SourceDatabaseExt> FileLoader for FileLoaderDelegate<&'_ T> {
161 } 160 }
162 fn resolve_path(&self, anchor: FileId, path: &str) -> Option<FileId> { 161 fn resolve_path(&self, anchor: FileId, path: &str) -> Option<FileId> {
163 // FIXME: this *somehow* should be platform agnostic... 162 // FIXME: this *somehow* should be platform agnostic...
164 if std::path::Path::new(path).is_absolute() { 163 let source_root = self.0.file_source_root(anchor);
165 let krate = *self.relevant_crates(anchor).iter().next()?; 164 let source_root = self.0.source_root(source_root);
166 let (extern_source_id, relative_file) = 165 source_root.file_set.resolve_path(anchor, path)
167 self.0.crate_graph()[krate].extern_source.extern_path(path.as_ref())?;
168
169 let source_root = self.0.source_root(SourceRootId(extern_source_id.0));
170 source_root.file_by_relative_path(&relative_file)
171 } else {
172 let rel_path = {
173 let mut rel_path = self.0.file_relative_path(anchor);
174 assert!(rel_path.pop());
175 rel_path.push(path);
176 rel_path.normalize()
177 };
178 let source_root = self.0.file_source_root(anchor);
179 let source_root = self.0.source_root(source_root);
180 source_root.file_by_relative_path(&rel_path)
181 }
182 } 166 }
183 167
184 fn relevant_crates(&self, file_id: FileId) -> Arc<FxHashSet<CrateId>> { 168 fn relevant_crates(&self, file_id: FileId) -> Arc<FxHashSet<CrateId>> {