aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_db/src/lib.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_db/src/lib.rs')
-rw-r--r--crates/ra_db/src/lib.rs79
1 files changed, 40 insertions, 39 deletions
diff --git a/crates/ra_db/src/lib.rs b/crates/ra_db/src/lib.rs
index fd4280de2..80ddb6058 100644
--- a/crates/ra_db/src/lib.rs
+++ b/crates/ra_db/src/lib.rs
@@ -7,12 +7,13 @@ use std::{panic, sync::Arc};
7 7
8use ra_prof::profile; 8use ra_prof::profile;
9use ra_syntax::{ast, Parse, SourceFile, TextRange, TextSize}; 9use ra_syntax::{ast, Parse, SourceFile, TextRange, TextSize};
10use rustc_hash::FxHashSet;
10 11
11pub use crate::{ 12pub use crate::{
12 cancellation::Canceled, 13 cancellation::Canceled,
13 input::{ 14 input::{
14 CrateGraph, CrateId, CrateName, Dependency, Edition, Env, ExternSource, ExternSourceId, 15 CrateData, CrateGraph, CrateId, CrateName, Dependency, Edition, Env, ExternSource,
15 FileId, ProcMacroId, SourceRoot, SourceRootId, 16 ExternSourceId, FileId, ProcMacroId, SourceRoot, SourceRootId,
16 }, 17 },
17}; 18};
18pub use relative_path::{RelativePath, RelativePathBuf}; 19pub use relative_path::{RelativePath, RelativePathBuf};
@@ -89,15 +90,13 @@ pub const DEFAULT_LRU_CAP: usize = 128;
89pub trait FileLoader { 90pub trait FileLoader {
90 /// Text of the file. 91 /// Text of the file.
91 fn file_text(&self, file_id: FileId) -> Arc<String>; 92 fn file_text(&self, file_id: FileId) -> Arc<String>;
92 fn resolve_relative_path(&self, anchor: FileId, relative_path: &RelativePath) 93 /// Note that we intentionally accept a `&str` and not a `&Path` here. This
93 -> Option<FileId>; 94 /// method exists to handle `#[path = "/some/path.rs"] mod foo;` and such,
94 fn relevant_crates(&self, file_id: FileId) -> Arc<Vec<CrateId>>; 95 /// so the input is guaranteed to be utf-8 string. We might introduce
95 96 /// `struct StrPath(str)` for clarity some day, but it's a bit messy, so we
96 fn resolve_extern_path( 97 /// get by with a `&str` for the time being.
97 &self, 98 fn resolve_path(&self, anchor: FileId, path: &str) -> Option<FileId>;
98 extern_id: ExternSourceId, 99 fn relevant_crates(&self, file_id: FileId) -> Arc<FxHashSet<CrateId>>;
99 relative_path: &RelativePath,
100 ) -> Option<FileId>;
101} 100}
102 101
103/// Database which stores all significant input facts: source code and project 102/// Database which stores all significant input facts: source code and project
@@ -135,16 +134,21 @@ pub trait SourceDatabaseExt: SourceDatabase {
135 #[salsa::input] 134 #[salsa::input]
136 fn source_root(&self, id: SourceRootId) -> Arc<SourceRoot>; 135 fn source_root(&self, id: SourceRootId) -> Arc<SourceRoot>;
137 136
138 fn source_root_crates(&self, id: SourceRootId) -> Arc<Vec<CrateId>>; 137 fn source_root_crates(&self, id: SourceRootId) -> Arc<FxHashSet<CrateId>>;
139} 138}
140 139
141fn source_root_crates( 140fn source_root_crates(
142 db: &(impl SourceDatabaseExt + SourceDatabase), 141 db: &(impl SourceDatabaseExt + SourceDatabase),
143 id: SourceRootId, 142 id: SourceRootId,
144) -> Arc<Vec<CrateId>> { 143) -> Arc<FxHashSet<CrateId>> {
145 let root = db.source_root(id);
146 let graph = db.crate_graph(); 144 let graph = db.crate_graph();
147 let res = root.walk().filter_map(|it| graph.crate_id_for_crate_root(it)).collect::<Vec<_>>(); 145 let res = graph
146 .iter()
147 .filter(|&krate| {
148 let root_file = graph[krate].root_file_id;
149 db.file_source_root(root_file) == id
150 })
151 .collect::<FxHashSet<_>>();
148 Arc::new(res) 152 Arc::new(res)
149} 153}
150 154
@@ -155,33 +159,30 @@ impl<T: SourceDatabaseExt> FileLoader for FileLoaderDelegate<&'_ T> {
155 fn file_text(&self, file_id: FileId) -> Arc<String> { 159 fn file_text(&self, file_id: FileId) -> Arc<String> {
156 SourceDatabaseExt::file_text(self.0, file_id) 160 SourceDatabaseExt::file_text(self.0, file_id)
157 } 161 }
158 fn resolve_relative_path( 162 fn resolve_path(&self, anchor: FileId, path: &str) -> Option<FileId> {
159 &self, 163 // FIXME: this *somehow* should be platform agnostic...
160 anchor: FileId, 164 if std::path::Path::new(path).is_absolute() {
161 relative_path: &RelativePath, 165 let krate = *self.relevant_crates(anchor).iter().next()?;
162 ) -> Option<FileId> { 166 let (extern_source_id, relative_file) =
163 let path = { 167 self.0.crate_graph()[krate].extern_source.extern_path(path.as_ref())?;
164 let mut path = self.0.file_relative_path(anchor); 168
165 assert!(path.pop()); 169 let source_root = self.0.source_root(SourceRootId(extern_source_id.0));
166 path.push(relative_path); 170 source_root.file_by_relative_path(&relative_file)
167 path.normalize() 171 } else {
168 }; 172 let rel_path = {
169 let source_root = self.0.file_source_root(anchor); 173 let mut rel_path = self.0.file_relative_path(anchor);
170 let source_root = self.0.source_root(source_root); 174 assert!(rel_path.pop());
171 source_root.file_by_relative_path(&path) 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 }
172 } 182 }
173 183
174 fn relevant_crates(&self, file_id: FileId) -> Arc<Vec<CrateId>> { 184 fn relevant_crates(&self, file_id: FileId) -> Arc<FxHashSet<CrateId>> {
175 let source_root = self.0.file_source_root(file_id); 185 let source_root = self.0.file_source_root(file_id);
176 self.0.source_root_crates(source_root) 186 self.0.source_root_crates(source_root)
177 } 187 }
178
179 fn resolve_extern_path(
180 &self,
181 extern_id: ExternSourceId,
182 relative_path: &RelativePath,
183 ) -> Option<FileId> {
184 let source_root = self.0.source_root(SourceRootId(extern_id.0));
185 source_root.file_by_relative_path(&relative_path)
186 }
187} 188}