diff options
Diffstat (limited to 'crates/ra_db/src')
-rw-r--r-- | crates/ra_db/src/fixture.rs | 63 | ||||
-rw-r--r-- | crates/ra_db/src/input.rs | 53 | ||||
-rw-r--r-- | crates/ra_db/src/lib.rs | 18 |
3 files changed, 118 insertions, 16 deletions
diff --git a/crates/ra_db/src/fixture.rs b/crates/ra_db/src/fixture.rs index 947d6ad56..3dc86ca2d 100644 --- a/crates/ra_db/src/fixture.rs +++ b/crates/ra_db/src/fixture.rs | |||
@@ -5,7 +5,7 @@ use std::sync::Arc; | |||
5 | 5 | ||
6 | use ra_cfg::CfgOptions; | 6 | use ra_cfg::CfgOptions; |
7 | use rustc_hash::FxHashMap; | 7 | use rustc_hash::FxHashMap; |
8 | use test_utils::{extract_offset, parse_fixture, CURSOR_MARKER}; | 8 | use test_utils::{extract_offset, parse_fixture, parse_single_fixture, CURSOR_MARKER}; |
9 | 9 | ||
10 | use crate::{ | 10 | use crate::{ |
11 | input::CrateName, CrateGraph, CrateId, Edition, Env, FileId, FilePosition, RelativePathBuf, | 11 | input::CrateName, CrateGraph, CrateId, Edition, Env, FileId, FilePosition, RelativePathBuf, |
@@ -45,23 +45,45 @@ pub trait WithFixture: Default + SourceDatabaseExt + 'static { | |||
45 | 45 | ||
46 | impl<DB: SourceDatabaseExt + Default + 'static> WithFixture for DB {} | 46 | impl<DB: SourceDatabaseExt + Default + 'static> WithFixture for DB {} |
47 | 47 | ||
48 | fn with_single_file(db: &mut dyn SourceDatabaseExt, text: &str) -> FileId { | 48 | fn with_single_file(db: &mut dyn SourceDatabaseExt, ra_fixture: &str) -> FileId { |
49 | let file_id = FileId(0); | 49 | let file_id = FileId(0); |
50 | let rel_path: RelativePathBuf = "/main.rs".into(); | 50 | let rel_path: RelativePathBuf = "/main.rs".into(); |
51 | 51 | ||
52 | let mut source_root = SourceRoot::new_local(); | 52 | let mut source_root = SourceRoot::new_local(); |
53 | source_root.insert_file(rel_path.clone(), file_id); | 53 | source_root.insert_file(rel_path.clone(), file_id); |
54 | 54 | ||
55 | let mut crate_graph = CrateGraph::default(); | 55 | let fixture = parse_single_fixture(ra_fixture); |
56 | crate_graph.add_crate_root( | 56 | |
57 | file_id, | 57 | let crate_graph = if let Some(entry) = fixture { |
58 | Edition::Edition2018, | 58 | let meta = match parse_meta(&entry.meta) { |
59 | None, | 59 | ParsedMeta::File(it) => it, |
60 | CfgOptions::default(), | 60 | _ => panic!("with_single_file only support file meta"), |
61 | Env::default(), | 61 | }; |
62 | ); | 62 | |
63 | 63 | let mut crate_graph = CrateGraph::default(); | |
64 | db.set_file_text(file_id, Arc::new(text.to_string())); | 64 | crate_graph.add_crate_root( |
65 | file_id, | ||
66 | meta.edition, | ||
67 | meta.krate, | ||
68 | meta.cfg, | ||
69 | meta.env, | ||
70 | Default::default(), | ||
71 | ); | ||
72 | crate_graph | ||
73 | } else { | ||
74 | let mut crate_graph = CrateGraph::default(); | ||
75 | crate_graph.add_crate_root( | ||
76 | file_id, | ||
77 | Edition::Edition2018, | ||
78 | None, | ||
79 | CfgOptions::default(), | ||
80 | Env::default(), | ||
81 | Default::default(), | ||
82 | ); | ||
83 | crate_graph | ||
84 | }; | ||
85 | |||
86 | db.set_file_text(file_id, Arc::new(ra_fixture.to_string())); | ||
65 | db.set_file_relative_path(file_id, rel_path); | 87 | db.set_file_relative_path(file_id, rel_path); |
66 | db.set_file_source_root(file_id, WORKSPACE); | 88 | db.set_file_source_root(file_id, WORKSPACE); |
67 | db.set_source_root(WORKSPACE, Arc::new(source_root)); | 89 | db.set_source_root(WORKSPACE, Arc::new(source_root)); |
@@ -104,7 +126,8 @@ fn with_files(db: &mut dyn SourceDatabaseExt, fixture: &str) -> Option<FilePosit | |||
104 | meta.edition, | 126 | meta.edition, |
105 | Some(krate.clone()), | 127 | Some(krate.clone()), |
106 | meta.cfg, | 128 | meta.cfg, |
107 | Env::default(), | 129 | meta.env, |
130 | Default::default(), | ||
108 | ); | 131 | ); |
109 | let prev = crates.insert(krate.clone(), crate_id); | 132 | let prev = crates.insert(krate.clone(), crate_id); |
110 | assert!(prev.is_none()); | 133 | assert!(prev.is_none()); |
@@ -141,6 +164,7 @@ fn with_files(db: &mut dyn SourceDatabaseExt, fixture: &str) -> Option<FilePosit | |||
141 | None, | 164 | None, |
142 | CfgOptions::default(), | 165 | CfgOptions::default(), |
143 | Env::default(), | 166 | Env::default(), |
167 | Default::default(), | ||
144 | ); | 168 | ); |
145 | } else { | 169 | } else { |
146 | for (from, to) in crate_deps { | 170 | for (from, to) in crate_deps { |
@@ -167,9 +191,10 @@ struct FileMeta { | |||
167 | deps: Vec<String>, | 191 | deps: Vec<String>, |
168 | cfg: CfgOptions, | 192 | cfg: CfgOptions, |
169 | edition: Edition, | 193 | edition: Edition, |
194 | env: Env, | ||
170 | } | 195 | } |
171 | 196 | ||
172 | //- /lib.rs crate:foo deps:bar,baz | 197 | //- /lib.rs crate:foo deps:bar,baz cfg:foo=a,bar=b env:OUTDIR=path/to,OTHER=foo) |
173 | fn parse_meta(meta: &str) -> ParsedMeta { | 198 | fn parse_meta(meta: &str) -> ParsedMeta { |
174 | let components = meta.split_ascii_whitespace().collect::<Vec<_>>(); | 199 | let components = meta.split_ascii_whitespace().collect::<Vec<_>>(); |
175 | 200 | ||
@@ -186,6 +211,7 @@ fn parse_meta(meta: &str) -> ParsedMeta { | |||
186 | let mut deps = Vec::new(); | 211 | let mut deps = Vec::new(); |
187 | let mut edition = Edition::Edition2018; | 212 | let mut edition = Edition::Edition2018; |
188 | let mut cfg = CfgOptions::default(); | 213 | let mut cfg = CfgOptions::default(); |
214 | let mut env = Env::default(); | ||
189 | for component in components[1..].iter() { | 215 | for component in components[1..].iter() { |
190 | let (key, value) = split1(component, ':').unwrap(); | 216 | let (key, value) = split1(component, ':').unwrap(); |
191 | match key { | 217 | match key { |
@@ -200,11 +226,18 @@ fn parse_meta(meta: &str) -> ParsedMeta { | |||
200 | } | 226 | } |
201 | } | 227 | } |
202 | } | 228 | } |
229 | "env" => { | ||
230 | for key in value.split(',') { | ||
231 | if let Some((k, v)) = split1(key, '=') { | ||
232 | env.set(k.into(), v.into()); | ||
233 | } | ||
234 | } | ||
235 | } | ||
203 | _ => panic!("bad component: {:?}", component), | 236 | _ => panic!("bad component: {:?}", component), |
204 | } | 237 | } |
205 | } | 238 | } |
206 | 239 | ||
207 | ParsedMeta::File(FileMeta { path, krate, deps, edition, cfg }) | 240 | ParsedMeta::File(FileMeta { path, krate, deps, edition, cfg, env }) |
208 | } | 241 | } |
209 | 242 | ||
210 | fn split1(haystack: &str, delim: char) -> Option<(&str, &str)> { | 243 | fn split1(haystack: &str, delim: char) -> Option<(&str, &str)> { |
diff --git a/crates/ra_db/src/input.rs b/crates/ra_db/src/input.rs index b77640b2b..06d40db96 100644 --- a/crates/ra_db/src/input.rs +++ b/crates/ra_db/src/input.rs | |||
@@ -113,6 +113,7 @@ pub struct CrateData { | |||
113 | pub display_name: Option<String>, | 113 | pub display_name: Option<String>, |
114 | pub cfg_options: CfgOptions, | 114 | pub cfg_options: CfgOptions, |
115 | pub env: Env, | 115 | pub env: Env, |
116 | pub extern_source: ExternSource, | ||
116 | pub dependencies: Vec<Dependency>, | 117 | pub dependencies: Vec<Dependency>, |
117 | } | 118 | } |
118 | 119 | ||
@@ -122,11 +123,22 @@ pub enum Edition { | |||
122 | Edition2015, | 123 | Edition2015, |
123 | } | 124 | } |
124 | 125 | ||
126 | #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] | ||
127 | pub struct ExternSourceId(pub u32); | ||
128 | |||
125 | #[derive(Default, Debug, Clone, PartialEq, Eq)] | 129 | #[derive(Default, Debug, Clone, PartialEq, Eq)] |
126 | pub struct Env { | 130 | pub struct Env { |
127 | entries: FxHashMap<String, String>, | 131 | entries: FxHashMap<String, String>, |
128 | } | 132 | } |
129 | 133 | ||
134 | // FIXME: Redesign vfs for solve the following limitation ? | ||
135 | // Note: Some env variables (e.g. OUT_DIR) are located outside of the | ||
136 | // crate. We store a map to allow remap it to ExternSourceId | ||
137 | #[derive(Default, Debug, Clone, PartialEq, Eq)] | ||
138 | pub struct ExternSource { | ||
139 | extern_paths: FxHashMap<String, ExternSourceId>, | ||
140 | } | ||
141 | |||
130 | #[derive(Debug, Clone, PartialEq, Eq)] | 142 | #[derive(Debug, Clone, PartialEq, Eq)] |
131 | pub struct Dependency { | 143 | pub struct Dependency { |
132 | pub crate_id: CrateId, | 144 | pub crate_id: CrateId, |
@@ -141,6 +153,7 @@ impl CrateGraph { | |||
141 | display_name: Option<String>, | 153 | display_name: Option<String>, |
142 | cfg_options: CfgOptions, | 154 | cfg_options: CfgOptions, |
143 | env: Env, | 155 | env: Env, |
156 | extern_source: ExternSource, | ||
144 | ) -> CrateId { | 157 | ) -> CrateId { |
145 | let data = CrateData { | 158 | let data = CrateData { |
146 | root_file_id: file_id, | 159 | root_file_id: file_id, |
@@ -148,6 +161,7 @@ impl CrateGraph { | |||
148 | display_name, | 161 | display_name, |
149 | cfg_options, | 162 | cfg_options, |
150 | env, | 163 | env, |
164 | extern_source, | ||
151 | dependencies: Vec::new(), | 165 | dependencies: Vec::new(), |
152 | }; | 166 | }; |
153 | let crate_id = CrateId(self.arena.len() as u32); | 167 | let crate_id = CrateId(self.arena.len() as u32); |
@@ -261,6 +275,37 @@ impl fmt::Display for Edition { | |||
261 | } | 275 | } |
262 | } | 276 | } |
263 | 277 | ||
278 | impl Env { | ||
279 | pub fn set(&mut self, env: &str, value: String) { | ||
280 | self.entries.insert(env.to_owned(), value); | ||
281 | } | ||
282 | |||
283 | pub fn get(&self, env: &str) -> Option<String> { | ||
284 | self.entries.get(env).cloned() | ||
285 | } | ||
286 | } | ||
287 | |||
288 | impl ExternSource { | ||
289 | pub fn extern_path(&self, path: &str) -> Option<(ExternSourceId, RelativePathBuf)> { | ||
290 | self.extern_paths.iter().find_map(|(root_path, id)| { | ||
291 | if path.starts_with(root_path) { | ||
292 | let mut rel_path = &path[root_path.len()..]; | ||
293 | if rel_path.starts_with("/") { | ||
294 | rel_path = &rel_path[1..]; | ||
295 | } | ||
296 | let rel_path = RelativePathBuf::from_path(rel_path).ok()?; | ||
297 | Some((id.clone(), rel_path)) | ||
298 | } else { | ||
299 | None | ||
300 | } | ||
301 | }) | ||
302 | } | ||
303 | |||
304 | pub fn set_extern_path(&mut self, root_path: &str, root: ExternSourceId) { | ||
305 | self.extern_paths.insert(root_path.to_owned(), root); | ||
306 | } | ||
307 | } | ||
308 | |||
264 | #[derive(Debug)] | 309 | #[derive(Debug)] |
265 | pub struct ParseEditionError { | 310 | pub struct ParseEditionError { |
266 | invalid_input: String, | 311 | invalid_input: String, |
@@ -290,6 +335,7 @@ mod tests { | |||
290 | None, | 335 | None, |
291 | CfgOptions::default(), | 336 | CfgOptions::default(), |
292 | Env::default(), | 337 | Env::default(), |
338 | Default::default(), | ||
293 | ); | 339 | ); |
294 | let crate2 = graph.add_crate_root( | 340 | let crate2 = graph.add_crate_root( |
295 | FileId(2u32), | 341 | FileId(2u32), |
@@ -297,6 +343,7 @@ mod tests { | |||
297 | None, | 343 | None, |
298 | CfgOptions::default(), | 344 | CfgOptions::default(), |
299 | Env::default(), | 345 | Env::default(), |
346 | Default::default(), | ||
300 | ); | 347 | ); |
301 | let crate3 = graph.add_crate_root( | 348 | let crate3 = graph.add_crate_root( |
302 | FileId(3u32), | 349 | FileId(3u32), |
@@ -304,6 +351,7 @@ mod tests { | |||
304 | None, | 351 | None, |
305 | CfgOptions::default(), | 352 | CfgOptions::default(), |
306 | Env::default(), | 353 | Env::default(), |
354 | Default::default(), | ||
307 | ); | 355 | ); |
308 | assert!(graph.add_dep(crate1, CrateName::new("crate2").unwrap(), crate2).is_ok()); | 356 | assert!(graph.add_dep(crate1, CrateName::new("crate2").unwrap(), crate2).is_ok()); |
309 | assert!(graph.add_dep(crate2, CrateName::new("crate3").unwrap(), crate3).is_ok()); | 357 | assert!(graph.add_dep(crate2, CrateName::new("crate3").unwrap(), crate3).is_ok()); |
@@ -319,6 +367,7 @@ mod tests { | |||
319 | None, | 367 | None, |
320 | CfgOptions::default(), | 368 | CfgOptions::default(), |
321 | Env::default(), | 369 | Env::default(), |
370 | Default::default(), | ||
322 | ); | 371 | ); |
323 | let crate2 = graph.add_crate_root( | 372 | let crate2 = graph.add_crate_root( |
324 | FileId(2u32), | 373 | FileId(2u32), |
@@ -326,6 +375,7 @@ mod tests { | |||
326 | None, | 375 | None, |
327 | CfgOptions::default(), | 376 | CfgOptions::default(), |
328 | Env::default(), | 377 | Env::default(), |
378 | Default::default(), | ||
329 | ); | 379 | ); |
330 | let crate3 = graph.add_crate_root( | 380 | let crate3 = graph.add_crate_root( |
331 | FileId(3u32), | 381 | FileId(3u32), |
@@ -333,6 +383,7 @@ mod tests { | |||
333 | None, | 383 | None, |
334 | CfgOptions::default(), | 384 | CfgOptions::default(), |
335 | Env::default(), | 385 | Env::default(), |
386 | Default::default(), | ||
336 | ); | 387 | ); |
337 | assert!(graph.add_dep(crate1, CrateName::new("crate2").unwrap(), crate2).is_ok()); | 388 | assert!(graph.add_dep(crate1, CrateName::new("crate2").unwrap(), crate2).is_ok()); |
338 | assert!(graph.add_dep(crate2, CrateName::new("crate3").unwrap(), crate3).is_ok()); | 389 | assert!(graph.add_dep(crate2, CrateName::new("crate3").unwrap(), crate3).is_ok()); |
@@ -347,6 +398,7 @@ mod tests { | |||
347 | None, | 398 | None, |
348 | CfgOptions::default(), | 399 | CfgOptions::default(), |
349 | Env::default(), | 400 | Env::default(), |
401 | Default::default(), | ||
350 | ); | 402 | ); |
351 | let crate2 = graph.add_crate_root( | 403 | let crate2 = graph.add_crate_root( |
352 | FileId(2u32), | 404 | FileId(2u32), |
@@ -354,6 +406,7 @@ mod tests { | |||
354 | None, | 406 | None, |
355 | CfgOptions::default(), | 407 | CfgOptions::default(), |
356 | Env::default(), | 408 | Env::default(), |
409 | Default::default(), | ||
357 | ); | 410 | ); |
358 | assert!(graph | 411 | assert!(graph |
359 | .add_dep(crate1, CrateName::normalize_dashes("crate-name-with-dashes"), crate2) | 412 | .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 fb002d717..d500d5e85 100644 --- a/crates/ra_db/src/lib.rs +++ b/crates/ra_db/src/lib.rs | |||
@@ -11,7 +11,8 @@ use ra_syntax::{ast, Parse, SourceFile, TextRange, TextUnit}; | |||
11 | pub use crate::{ | 11 | pub use crate::{ |
12 | cancellation::Canceled, | 12 | cancellation::Canceled, |
13 | input::{ | 13 | input::{ |
14 | CrateGraph, CrateId, CrateName, Dependency, Edition, Env, FileId, SourceRoot, SourceRootId, | 14 | CrateGraph, CrateId, CrateName, Dependency, Edition, Env, ExternSource, ExternSourceId, |
15 | FileId, SourceRoot, SourceRootId, | ||
15 | }, | 16 | }, |
16 | }; | 17 | }; |
17 | pub use relative_path::{RelativePath, RelativePathBuf}; | 18 | pub use relative_path::{RelativePath, RelativePathBuf}; |
@@ -87,6 +88,12 @@ pub trait FileLoader { | |||
87 | fn resolve_relative_path(&self, anchor: FileId, relative_path: &RelativePath) | 88 | fn resolve_relative_path(&self, anchor: FileId, relative_path: &RelativePath) |
88 | -> Option<FileId>; | 89 | -> Option<FileId>; |
89 | fn relevant_crates(&self, file_id: FileId) -> Arc<Vec<CrateId>>; | 90 | fn relevant_crates(&self, file_id: FileId) -> Arc<Vec<CrateId>>; |
91 | |||
92 | fn resolve_extern_path( | ||
93 | &self, | ||
94 | extern_id: ExternSourceId, | ||
95 | relative_path: &RelativePath, | ||
96 | ) -> Option<FileId>; | ||
90 | } | 97 | } |
91 | 98 | ||
92 | /// Database which stores all significant input facts: source code and project | 99 | /// Database which stores all significant input facts: source code and project |
@@ -164,4 +171,13 @@ impl<T: SourceDatabaseExt> FileLoader for FileLoaderDelegate<&'_ T> { | |||
164 | let source_root = self.0.file_source_root(file_id); | 171 | let source_root = self.0.file_source_root(file_id); |
165 | self.0.source_root_crates(source_root) | 172 | self.0.source_root_crates(source_root) |
166 | } | 173 | } |
174 | |||
175 | fn resolve_extern_path( | ||
176 | &self, | ||
177 | extern_id: ExternSourceId, | ||
178 | relative_path: &RelativePath, | ||
179 | ) -> Option<FileId> { | ||
180 | let source_root = self.0.source_root(SourceRootId(extern_id.0)); | ||
181 | source_root.file_by_relative_path(&relative_path) | ||
182 | } | ||
167 | } | 183 | } |