diff options
Diffstat (limited to 'crates')
-rw-r--r-- | crates/ra_cargo_watch/src/lib.rs | 175 | ||||
-rw-r--r-- | crates/ra_db/src/input.rs | 21 | ||||
-rw-r--r-- | crates/ra_project_model/Cargo.toml | 1 | ||||
-rw-r--r-- | crates/ra_project_model/src/cargo_workspace.rs | 67 | ||||
-rw-r--r-- | crates/ra_project_model/src/json_project.rs | 1 | ||||
-rw-r--r-- | crates/ra_project_model/src/lib.rs | 57 | ||||
-rw-r--r-- | crates/rust-analyzer/src/bin/args.rs | 14 | ||||
-rw-r--r-- | crates/rust-analyzer/src/bin/main.rs | 32 | ||||
-rw-r--r-- | crates/rust-analyzer/src/cli/analysis_bench.rs | 9 | ||||
-rw-r--r-- | crates/rust-analyzer/src/cli/analysis_stats.rs | 3 | ||||
-rw-r--r-- | crates/rust-analyzer/src/cli/load_cargo.rs | 70 | ||||
-rw-r--r-- | crates/rust-analyzer/src/config.rs | 4 | ||||
-rw-r--r-- | crates/rust-analyzer/src/main_loop.rs | 1 | ||||
-rw-r--r-- | crates/rust-analyzer/src/world.rs | 20 |
14 files changed, 306 insertions, 169 deletions
diff --git a/crates/ra_cargo_watch/src/lib.rs b/crates/ra_cargo_watch/src/lib.rs index 1a6926db3..bffe5eb00 100644 --- a/crates/ra_cargo_watch/src/lib.rs +++ b/crates/ra_cargo_watch/src/lib.rs | |||
@@ -9,8 +9,8 @@ use lsp_types::{ | |||
9 | }; | 9 | }; |
10 | use std::{ | 10 | use std::{ |
11 | io::{BufRead, BufReader}, | 11 | io::{BufRead, BufReader}, |
12 | path::PathBuf, | 12 | path::{Path, PathBuf}, |
13 | process::{Command, Stdio}, | 13 | process::{Child, Command, Stdio}, |
14 | thread::JoinHandle, | 14 | thread::JoinHandle, |
15 | time::Instant, | 15 | time::Instant, |
16 | }; | 16 | }; |
@@ -246,18 +246,71 @@ enum CheckEvent { | |||
246 | End, | 246 | End, |
247 | } | 247 | } |
248 | 248 | ||
249 | pub fn run_cargo( | ||
250 | args: &[String], | ||
251 | current_dir: Option<&Path>, | ||
252 | on_message: &mut dyn FnMut(cargo_metadata::Message) -> bool, | ||
253 | ) -> Child { | ||
254 | let mut command = Command::new("cargo"); | ||
255 | if let Some(current_dir) = current_dir { | ||
256 | command.current_dir(current_dir); | ||
257 | } | ||
258 | |||
259 | let mut child = command | ||
260 | .args(args) | ||
261 | .stdout(Stdio::piped()) | ||
262 | .stderr(Stdio::null()) | ||
263 | .stdin(Stdio::null()) | ||
264 | .spawn() | ||
265 | .expect("couldn't launch cargo"); | ||
266 | |||
267 | // We manually read a line at a time, instead of using serde's | ||
268 | // stream deserializers, because the deserializer cannot recover | ||
269 | // from an error, resulting in it getting stuck, because we try to | ||
270 | // be resillient against failures. | ||
271 | // | ||
272 | // Because cargo only outputs one JSON object per line, we can | ||
273 | // simply skip a line if it doesn't parse, which just ignores any | ||
274 | // erroneus output. | ||
275 | let stdout = BufReader::new(child.stdout.take().unwrap()); | ||
276 | for line in stdout.lines() { | ||
277 | let line = match line { | ||
278 | Ok(line) => line, | ||
279 | Err(err) => { | ||
280 | log::error!("Couldn't read line from cargo: {}", err); | ||
281 | continue; | ||
282 | } | ||
283 | }; | ||
284 | |||
285 | let message = serde_json::from_str::<cargo_metadata::Message>(&line); | ||
286 | let message = match message { | ||
287 | Ok(message) => message, | ||
288 | Err(err) => { | ||
289 | log::error!("Invalid json from cargo check, ignoring ({}): {:?} ", err, line); | ||
290 | continue; | ||
291 | } | ||
292 | }; | ||
293 | |||
294 | if !on_message(message) { | ||
295 | break; | ||
296 | } | ||
297 | } | ||
298 | |||
299 | child | ||
300 | } | ||
301 | |||
249 | impl WatchThread { | 302 | impl WatchThread { |
250 | fn dummy() -> WatchThread { | 303 | fn dummy() -> WatchThread { |
251 | WatchThread { handle: None, message_recv: never() } | 304 | WatchThread { handle: None, message_recv: never() } |
252 | } | 305 | } |
253 | 306 | ||
254 | fn new(options: &CheckOptions, workspace_root: &PathBuf) -> WatchThread { | 307 | fn new(options: &CheckOptions, workspace_root: &Path) -> WatchThread { |
255 | let mut args: Vec<String> = vec![ | 308 | let mut args: Vec<String> = vec![ |
256 | options.command.clone(), | 309 | options.command.clone(), |
257 | "--workspace".to_string(), | 310 | "--workspace".to_string(), |
258 | "--message-format=json".to_string(), | 311 | "--message-format=json".to_string(), |
259 | "--manifest-path".to_string(), | 312 | "--manifest-path".to_string(), |
260 | format!("{}/Cargo.toml", workspace_root.to_string_lossy()), | 313 | format!("{}/Cargo.toml", workspace_root.display()), |
261 | ]; | 314 | ]; |
262 | if options.all_targets { | 315 | if options.all_targets { |
263 | args.push("--all-targets".to_string()); | 316 | args.push("--all-targets".to_string()); |
@@ -265,83 +318,47 @@ impl WatchThread { | |||
265 | args.extend(options.args.iter().cloned()); | 318 | args.extend(options.args.iter().cloned()); |
266 | 319 | ||
267 | let (message_send, message_recv) = unbounded(); | 320 | let (message_send, message_recv) = unbounded(); |
268 | let enabled = options.enable; | 321 | let workspace_root = workspace_root.to_owned(); |
269 | let handle = std::thread::spawn(move || { | 322 | let handle = if options.enable { |
270 | if !enabled { | 323 | Some(std::thread::spawn(move || { |
271 | return; | 324 | // If we trigger an error here, we will do so in the loop instead, |
272 | } | 325 | // which will break out of the loop, and continue the shutdown |
273 | 326 | let _ = message_send.send(CheckEvent::Begin); | |
274 | let mut command = Command::new("cargo") | 327 | |
275 | .args(&args) | 328 | let mut child = run_cargo(&args, Some(&workspace_root), &mut |message| { |
276 | .stdout(Stdio::piped()) | 329 | // Skip certain kinds of messages to only spend time on what's useful |
277 | .stderr(Stdio::null()) | 330 | match &message { |
278 | .stdin(Stdio::null()) | 331 | Message::CompilerArtifact(artifact) if artifact.fresh => return true, |
279 | .spawn() | 332 | Message::BuildScriptExecuted(_) => return true, |
280 | .expect("couldn't launch cargo"); | 333 | Message::Unknown => return true, |
281 | 334 | _ => {} | |
282 | // If we trigger an error here, we will do so in the loop instead, | ||
283 | // which will break out of the loop, and continue the shutdown | ||
284 | let _ = message_send.send(CheckEvent::Begin); | ||
285 | |||
286 | // We manually read a line at a time, instead of using serde's | ||
287 | // stream deserializers, because the deserializer cannot recover | ||
288 | // from an error, resulting in it getting stuck, because we try to | ||
289 | // be resillient against failures. | ||
290 | // | ||
291 | // Because cargo only outputs one JSON object per line, we can | ||
292 | // simply skip a line if it doesn't parse, which just ignores any | ||
293 | // erroneus output. | ||
294 | let stdout = BufReader::new(command.stdout.take().unwrap()); | ||
295 | for line in stdout.lines() { | ||
296 | let line = match line { | ||
297 | Ok(line) => line, | ||
298 | Err(err) => { | ||
299 | log::error!("Couldn't read line from cargo: {}", err); | ||
300 | continue; | ||
301 | } | ||
302 | }; | ||
303 | |||
304 | let message = serde_json::from_str::<cargo_metadata::Message>(&line); | ||
305 | let message = match message { | ||
306 | Ok(message) => message, | ||
307 | Err(err) => { | ||
308 | log::error!( | ||
309 | "Invalid json from cargo check, ignoring ({}): {:?} ", | ||
310 | err, | ||
311 | line | ||
312 | ); | ||
313 | continue; | ||
314 | } | 335 | } |
315 | }; | ||
316 | |||
317 | // Skip certain kinds of messages to only spend time on what's useful | ||
318 | match &message { | ||
319 | Message::CompilerArtifact(artifact) if artifact.fresh => continue, | ||
320 | Message::BuildScriptExecuted(_) => continue, | ||
321 | Message::Unknown => continue, | ||
322 | _ => {} | ||
323 | } | ||
324 | 336 | ||
325 | match message_send.send(CheckEvent::Msg(message)) { | 337 | match message_send.send(CheckEvent::Msg(message)) { |
326 | Ok(()) => {} | 338 | Ok(()) => {} |
327 | Err(_err) => { | 339 | Err(_err) => { |
328 | // The send channel was closed, so we want to shutdown | 340 | // The send channel was closed, so we want to shutdown |
329 | break; | 341 | return false; |
330 | } | 342 | } |
331 | } | 343 | }; |
332 | } | 344 | |
333 | 345 | true | |
334 | // We can ignore any error here, as we are already in the progress | 346 | }); |
335 | // of shutting down. | 347 | |
336 | let _ = message_send.send(CheckEvent::End); | 348 | // We can ignore any error here, as we are already in the progress |
337 | 349 | // of shutting down. | |
338 | // It is okay to ignore the result, as it only errors if the process is already dead | 350 | let _ = message_send.send(CheckEvent::End); |
339 | let _ = command.kill(); | 351 | |
340 | 352 | // It is okay to ignore the result, as it only errors if the process is already dead | |
341 | // Again, we don't care about the exit status so just ignore the result | 353 | let _ = child.kill(); |
342 | let _ = command.wait(); | 354 | |
343 | }); | 355 | // Again, we don't care about the exit status so just ignore the result |
344 | WatchThread { handle: Some(handle), message_recv } | 356 | let _ = child.wait(); |
357 | })) | ||
358 | } else { | ||
359 | None | ||
360 | }; | ||
361 | WatchThread { handle, message_recv } | ||
345 | } | 362 | } |
346 | } | 363 | } |
347 | 364 | ||
diff --git a/crates/ra_db/src/input.rs b/crates/ra_db/src/input.rs index bde843001..e371f849d 100644 --- a/crates/ra_db/src/input.rs +++ b/crates/ra_db/src/input.rs | |||
@@ -6,7 +6,11 @@ | |||
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 | ||
9 | use std::{fmt, ops, str::FromStr}; | 9 | use std::{ |
10 | fmt, ops, | ||
11 | path::{Path, PathBuf}, | ||
12 | str::FromStr, | ||
13 | }; | ||
10 | 14 | ||
11 | use ra_cfg::CfgOptions; | 15 | use ra_cfg::CfgOptions; |
12 | use ra_syntax::SmolStr; | 16 | use ra_syntax::SmolStr; |
@@ -144,7 +148,7 @@ pub struct Env { | |||
144 | // crate. We store a map to allow remap it to ExternSourceId | 148 | // crate. We store a map to allow remap it to ExternSourceId |
145 | #[derive(Default, Debug, Clone, PartialEq, Eq)] | 149 | #[derive(Default, Debug, Clone, PartialEq, Eq)] |
146 | pub struct ExternSource { | 150 | pub struct ExternSource { |
147 | extern_paths: FxHashMap<String, ExternSourceId>, | 151 | extern_paths: FxHashMap<PathBuf, ExternSourceId>, |
148 | } | 152 | } |
149 | 153 | ||
150 | #[derive(Debug, Clone, PartialEq, Eq)] | 154 | #[derive(Debug, Clone, PartialEq, Eq)] |
@@ -294,13 +298,10 @@ impl Env { | |||
294 | } | 298 | } |
295 | 299 | ||
296 | impl ExternSource { | 300 | impl ExternSource { |
297 | pub fn extern_path(&self, path: &str) -> Option<(ExternSourceId, RelativePathBuf)> { | 301 | pub fn extern_path(&self, path: impl AsRef<Path>) -> Option<(ExternSourceId, RelativePathBuf)> { |
302 | let path = path.as_ref(); | ||
298 | self.extern_paths.iter().find_map(|(root_path, id)| { | 303 | self.extern_paths.iter().find_map(|(root_path, id)| { |
299 | if path.starts_with(root_path) { | 304 | if let Ok(rel_path) = path.strip_prefix(root_path) { |
300 | let mut rel_path = &path[root_path.len()..]; | ||
301 | if rel_path.starts_with("/") { | ||
302 | rel_path = &rel_path[1..]; | ||
303 | } | ||
304 | let rel_path = RelativePathBuf::from_path(rel_path).ok()?; | 305 | let rel_path = RelativePathBuf::from_path(rel_path).ok()?; |
305 | Some((id.clone(), rel_path)) | 306 | Some((id.clone(), rel_path)) |
306 | } else { | 307 | } else { |
@@ -309,8 +310,8 @@ impl ExternSource { | |||
309 | }) | 310 | }) |
310 | } | 311 | } |
311 | 312 | ||
312 | pub fn set_extern_path(&mut self, root_path: &str, root: ExternSourceId) { | 313 | pub fn set_extern_path(&mut self, root_path: &Path, root: ExternSourceId) { |
313 | self.extern_paths.insert(root_path.to_owned(), root); | 314 | self.extern_paths.insert(root_path.to_path_buf(), root); |
314 | } | 315 | } |
315 | } | 316 | } |
316 | 317 | ||
diff --git a/crates/ra_project_model/Cargo.toml b/crates/ra_project_model/Cargo.toml index 6252241bf..22300548a 100644 --- a/crates/ra_project_model/Cargo.toml +++ b/crates/ra_project_model/Cargo.toml | |||
@@ -16,6 +16,7 @@ cargo_metadata = "0.9.1" | |||
16 | ra_arena = { path = "../ra_arena" } | 16 | ra_arena = { path = "../ra_arena" } |
17 | ra_db = { path = "../ra_db" } | 17 | ra_db = { path = "../ra_db" } |
18 | ra_cfg = { path = "../ra_cfg" } | 18 | ra_cfg = { path = "../ra_cfg" } |
19 | ra_cargo_watch = { path = "../ra_cargo_watch" } | ||
19 | 20 | ||
20 | serde = { version = "1.0.104", features = ["derive"] } | 21 | serde = { version = "1.0.104", features = ["derive"] } |
21 | serde_json = "1.0.48" | 22 | serde_json = "1.0.48" |
diff --git a/crates/ra_project_model/src/cargo_workspace.rs b/crates/ra_project_model/src/cargo_workspace.rs index 4fea459d5..10ecfa951 100644 --- a/crates/ra_project_model/src/cargo_workspace.rs +++ b/crates/ra_project_model/src/cargo_workspace.rs | |||
@@ -3,8 +3,9 @@ | |||
3 | use std::path::{Path, PathBuf}; | 3 | use std::path::{Path, PathBuf}; |
4 | 4 | ||
5 | use anyhow::{Context, Result}; | 5 | use anyhow::{Context, Result}; |
6 | use cargo_metadata::{CargoOpt, MetadataCommand}; | 6 | use cargo_metadata::{CargoOpt, Message, MetadataCommand, PackageId}; |
7 | use ra_arena::{impl_arena_id, Arena, RawId}; | 7 | use ra_arena::{impl_arena_id, Arena, RawId}; |
8 | use ra_cargo_watch::run_cargo; | ||
8 | use ra_db::Edition; | 9 | use ra_db::Edition; |
9 | use rustc_hash::FxHashMap; | 10 | use rustc_hash::FxHashMap; |
10 | use serde::Deserialize; | 11 | use serde::Deserialize; |
@@ -35,11 +36,19 @@ pub struct CargoFeatures { | |||
35 | /// List of features to activate. | 36 | /// List of features to activate. |
36 | /// This will be ignored if `cargo_all_features` is true. | 37 | /// This will be ignored if `cargo_all_features` is true. |
37 | pub features: Vec<String>, | 38 | pub features: Vec<String>, |
39 | |||
40 | /// Runs cargo check on launch to figure out the correct values of OUT_DIR | ||
41 | pub load_out_dirs_from_check: bool, | ||
38 | } | 42 | } |
39 | 43 | ||
40 | impl Default for CargoFeatures { | 44 | impl Default for CargoFeatures { |
41 | fn default() -> Self { | 45 | fn default() -> Self { |
42 | CargoFeatures { no_default_features: false, all_features: true, features: Vec::new() } | 46 | CargoFeatures { |
47 | no_default_features: false, | ||
48 | all_features: true, | ||
49 | features: Vec::new(), | ||
50 | load_out_dirs_from_check: false, | ||
51 | } | ||
43 | } | 52 | } |
44 | } | 53 | } |
45 | 54 | ||
@@ -60,6 +69,7 @@ struct PackageData { | |||
60 | dependencies: Vec<PackageDependency>, | 69 | dependencies: Vec<PackageDependency>, |
61 | edition: Edition, | 70 | edition: Edition, |
62 | features: Vec<String>, | 71 | features: Vec<String>, |
72 | out_dir: Option<PathBuf>, | ||
63 | } | 73 | } |
64 | 74 | ||
65 | #[derive(Debug, Clone)] | 75 | #[derive(Debug, Clone)] |
@@ -131,6 +141,9 @@ impl Package { | |||
131 | ) -> impl Iterator<Item = &'a PackageDependency> + 'a { | 141 | ) -> impl Iterator<Item = &'a PackageDependency> + 'a { |
132 | ws.packages[self].dependencies.iter() | 142 | ws.packages[self].dependencies.iter() |
133 | } | 143 | } |
144 | pub fn out_dir(self, ws: &CargoWorkspace) -> Option<&Path> { | ||
145 | ws.packages[self].out_dir.as_ref().map(PathBuf::as_path) | ||
146 | } | ||
134 | } | 147 | } |
135 | 148 | ||
136 | impl Target { | 149 | impl Target { |
@@ -173,6 +186,12 @@ impl CargoWorkspace { | |||
173 | let meta = meta.exec().with_context(|| { | 186 | let meta = meta.exec().with_context(|| { |
174 | format!("Failed to run `cargo metadata --manifest-path {}`", cargo_toml.display()) | 187 | format!("Failed to run `cargo metadata --manifest-path {}`", cargo_toml.display()) |
175 | })?; | 188 | })?; |
189 | |||
190 | let mut out_dir_by_id = FxHashMap::default(); | ||
191 | if cargo_features.load_out_dirs_from_check { | ||
192 | out_dir_by_id = load_out_dirs(cargo_toml, cargo_features); | ||
193 | } | ||
194 | |||
176 | let mut pkg_by_id = FxHashMap::default(); | 195 | let mut pkg_by_id = FxHashMap::default(); |
177 | let mut packages = Arena::default(); | 196 | let mut packages = Arena::default(); |
178 | let mut targets = Arena::default(); | 197 | let mut targets = Arena::default(); |
@@ -193,6 +212,7 @@ impl CargoWorkspace { | |||
193 | edition, | 212 | edition, |
194 | dependencies: Vec::new(), | 213 | dependencies: Vec::new(), |
195 | features: Vec::new(), | 214 | features: Vec::new(), |
215 | out_dir: out_dir_by_id.get(&id).cloned(), | ||
196 | }); | 216 | }); |
197 | let pkg_data = &mut packages[pkg]; | 217 | let pkg_data = &mut packages[pkg]; |
198 | pkg_by_id.insert(id, pkg); | 218 | pkg_by_id.insert(id, pkg); |
@@ -252,3 +272,46 @@ impl CargoWorkspace { | |||
252 | &self.workspace_root | 272 | &self.workspace_root |
253 | } | 273 | } |
254 | } | 274 | } |
275 | |||
276 | pub fn load_out_dirs( | ||
277 | cargo_toml: &Path, | ||
278 | cargo_features: &CargoFeatures, | ||
279 | ) -> FxHashMap<PackageId, PathBuf> { | ||
280 | let mut args: Vec<String> = vec![ | ||
281 | "check".to_string(), | ||
282 | "--message-format=json".to_string(), | ||
283 | "--manifest-path".to_string(), | ||
284 | format!("{}", cargo_toml.display()), | ||
285 | ]; | ||
286 | |||
287 | if cargo_features.all_features { | ||
288 | args.push("--all-features".to_string()); | ||
289 | } else if cargo_features.no_default_features { | ||
290 | // FIXME: `NoDefaultFeatures` is mutual exclusive with `SomeFeatures` | ||
291 | // https://github.com/oli-obk/cargo_metadata/issues/79 | ||
292 | args.push("--no-default-features".to_string()); | ||
293 | } else if !cargo_features.features.is_empty() { | ||
294 | for feature in &cargo_features.features { | ||
295 | args.push(feature.clone()); | ||
296 | } | ||
297 | } | ||
298 | |||
299 | let mut res = FxHashMap::default(); | ||
300 | let mut child = run_cargo(&args, cargo_toml.parent(), &mut |message| { | ||
301 | match message { | ||
302 | Message::BuildScriptExecuted(message) => { | ||
303 | let package_id = message.package_id; | ||
304 | let out_dir = message.out_dir; | ||
305 | res.insert(package_id, out_dir); | ||
306 | } | ||
307 | |||
308 | Message::CompilerArtifact(_) => (), | ||
309 | Message::CompilerMessage(_) => (), | ||
310 | Message::Unknown => (), | ||
311 | } | ||
312 | true | ||
313 | }); | ||
314 | |||
315 | let _ = child.wait(); | ||
316 | res | ||
317 | } | ||
diff --git a/crates/ra_project_model/src/json_project.rs b/crates/ra_project_model/src/json_project.rs index 1bacb1d09..336446e58 100644 --- a/crates/ra_project_model/src/json_project.rs +++ b/crates/ra_project_model/src/json_project.rs | |||
@@ -22,6 +22,7 @@ pub struct Crate { | |||
22 | pub(crate) deps: Vec<Dep>, | 22 | pub(crate) deps: Vec<Dep>, |
23 | pub(crate) atom_cfgs: FxHashSet<String>, | 23 | pub(crate) atom_cfgs: FxHashSet<String>, |
24 | pub(crate) key_value_cfgs: FxHashMap<String, String>, | 24 | pub(crate) key_value_cfgs: FxHashMap<String, String>, |
25 | pub(crate) out_dir: Option<PathBuf>, | ||
25 | } | 26 | } |
26 | 27 | ||
27 | #[derive(Clone, Copy, Debug, Deserialize)] | 28 | #[derive(Clone, Copy, Debug, Deserialize)] |
diff --git a/crates/ra_project_model/src/lib.rs b/crates/ra_project_model/src/lib.rs index 897874813..081b1fec2 100644 --- a/crates/ra_project_model/src/lib.rs +++ b/crates/ra_project_model/src/lib.rs | |||
@@ -150,6 +150,29 @@ impl ProjectWorkspace { | |||
150 | } | 150 | } |
151 | } | 151 | } |
152 | 152 | ||
153 | pub fn out_dirs(&self) -> Vec<PathBuf> { | ||
154 | match self { | ||
155 | ProjectWorkspace::Json { project } => { | ||
156 | let mut out_dirs = Vec::with_capacity(project.crates.len()); | ||
157 | for krate in &project.crates { | ||
158 | if let Some(out_dir) = &krate.out_dir { | ||
159 | out_dirs.push(out_dir.to_path_buf()); | ||
160 | } | ||
161 | } | ||
162 | out_dirs | ||
163 | } | ||
164 | ProjectWorkspace::Cargo { cargo, sysroot: _sysroot } => { | ||
165 | let mut out_dirs = Vec::with_capacity(cargo.packages().len()); | ||
166 | for pkg in cargo.packages() { | ||
167 | if let Some(out_dir) = pkg.out_dir(&cargo) { | ||
168 | out_dirs.push(out_dir.to_path_buf()); | ||
169 | } | ||
170 | } | ||
171 | out_dirs | ||
172 | } | ||
173 | } | ||
174 | } | ||
175 | |||
153 | pub fn n_packages(&self) -> usize { | 176 | pub fn n_packages(&self) -> usize { |
154 | match self { | 177 | match self { |
155 | ProjectWorkspace::Json { project } => project.crates.len(), | 178 | ProjectWorkspace::Json { project } => project.crates.len(), |
@@ -162,7 +185,7 @@ impl ProjectWorkspace { | |||
162 | pub fn to_crate_graph( | 185 | pub fn to_crate_graph( |
163 | &self, | 186 | &self, |
164 | default_cfg_options: &CfgOptions, | 187 | default_cfg_options: &CfgOptions, |
165 | outdirs: &FxHashMap<String, (ExternSourceId, String)>, | 188 | extern_source_roots: &FxHashMap<PathBuf, ExternSourceId>, |
166 | load: &mut dyn FnMut(&Path) -> Option<FileId>, | 189 | load: &mut dyn FnMut(&Path) -> Option<FileId>, |
167 | ) -> CrateGraph { | 190 | ) -> CrateGraph { |
168 | let mut crate_graph = CrateGraph::default(); | 191 | let mut crate_graph = CrateGraph::default(); |
@@ -187,6 +210,16 @@ impl ProjectWorkspace { | |||
187 | opts | 210 | opts |
188 | }; | 211 | }; |
189 | 212 | ||
213 | let mut env = Env::default(); | ||
214 | let mut extern_source = ExternSource::default(); | ||
215 | if let Some(out_dir) = &krate.out_dir { | ||
216 | // FIXME: We probably mangle non UTF-8 paths here, figure out a better solution | ||
217 | env.set("OUT_DIR", out_dir.to_string_lossy().to_string()); | ||
218 | if let Some(&extern_source_id) = extern_source_roots.get(out_dir) { | ||
219 | extern_source.set_extern_path(&out_dir, extern_source_id); | ||
220 | } | ||
221 | } | ||
222 | |||
190 | // FIXME: No crate name in json definition such that we cannot add OUT_DIR to env | 223 | // FIXME: No crate name in json definition such that we cannot add OUT_DIR to env |
191 | crates.insert( | 224 | crates.insert( |
192 | crate_id, | 225 | crate_id, |
@@ -196,8 +229,8 @@ impl ProjectWorkspace { | |||
196 | // FIXME json definitions can store the crate name | 229 | // FIXME json definitions can store the crate name |
197 | None, | 230 | None, |
198 | cfg_options, | 231 | cfg_options, |
199 | Env::default(), | 232 | env, |
200 | Default::default(), | 233 | extern_source, |
201 | ), | 234 | ), |
202 | ); | 235 | ); |
203 | } | 236 | } |
@@ -235,13 +268,8 @@ impl ProjectWorkspace { | |||
235 | opts | 268 | opts |
236 | }; | 269 | }; |
237 | 270 | ||
238 | let mut env = Env::default(); | 271 | let env = Env::default(); |
239 | let mut extern_source = ExternSource::default(); | 272 | let extern_source = ExternSource::default(); |
240 | if let Some((id, path)) = outdirs.get(krate.name(&sysroot)) { | ||
241 | env.set("OUT_DIR", path.clone()); | ||
242 | extern_source.set_extern_path(&path, *id); | ||
243 | } | ||
244 | |||
245 | let crate_id = crate_graph.add_crate_root( | 273 | let crate_id = crate_graph.add_crate_root( |
246 | file_id, | 274 | file_id, |
247 | Edition::Edition2018, | 275 | Edition::Edition2018, |
@@ -292,9 +320,12 @@ impl ProjectWorkspace { | |||
292 | }; | 320 | }; |
293 | let mut env = Env::default(); | 321 | let mut env = Env::default(); |
294 | let mut extern_source = ExternSource::default(); | 322 | let mut extern_source = ExternSource::default(); |
295 | if let Some((id, path)) = outdirs.get(pkg.name(&cargo)) { | 323 | if let Some(out_dir) = pkg.out_dir(cargo) { |
296 | env.set("OUT_DIR", path.clone()); | 324 | // FIXME: We probably mangle non UTF-8 paths here, figure out a better solution |
297 | extern_source.set_extern_path(&path, *id); | 325 | env.set("OUT_DIR", out_dir.to_string_lossy().to_string()); |
326 | if let Some(&extern_source_id) = extern_source_roots.get(out_dir) { | ||
327 | extern_source.set_extern_path(&out_dir, extern_source_id); | ||
328 | } | ||
298 | } | 329 | } |
299 | let crate_id = crate_graph.add_crate_root( | 330 | let crate_id = crate_graph.add_crate_root( |
300 | file_id, | 331 | file_id, |
diff --git a/crates/rust-analyzer/src/bin/args.rs b/crates/rust-analyzer/src/bin/args.rs index 993d3d0b6..3cf394bb4 100644 --- a/crates/rust-analyzer/src/bin/args.rs +++ b/crates/rust-analyzer/src/bin/args.rs | |||
@@ -28,10 +28,12 @@ pub(crate) enum Command { | |||
28 | only: Option<String>, | 28 | only: Option<String>, |
29 | with_deps: bool, | 29 | with_deps: bool, |
30 | path: PathBuf, | 30 | path: PathBuf, |
31 | load_output_dirs: bool, | ||
31 | }, | 32 | }, |
32 | Bench { | 33 | Bench { |
33 | path: PathBuf, | 34 | path: PathBuf, |
34 | what: BenchWhat, | 35 | what: BenchWhat, |
36 | load_output_dirs: bool, | ||
35 | }, | 37 | }, |
36 | RunServer, | 38 | RunServer, |
37 | Version, | 39 | Version, |
@@ -136,8 +138,9 @@ USAGE: | |||
136 | rust-analyzer analysis-stats [FLAGS] [OPTIONS] [PATH] | 138 | rust-analyzer analysis-stats [FLAGS] [OPTIONS] [PATH] |
137 | 139 | ||
138 | FLAGS: | 140 | FLAGS: |
139 | -h, --help Prints help information | 141 | -h, --help Prints help information |
140 | --memory-usage | 142 | --memory-usage |
143 | --load-output-dirs Load OUT_DIR values by running `cargo check` before analysis | ||
141 | -v, --verbose | 144 | -v, --verbose |
142 | -q, --quiet | 145 | -q, --quiet |
143 | 146 | ||
@@ -154,6 +157,7 @@ ARGS: | |||
154 | let memory_usage = matches.contains("--memory-usage"); | 157 | let memory_usage = matches.contains("--memory-usage"); |
155 | let only: Option<String> = matches.opt_value_from_str(["-o", "--only"])?; | 158 | let only: Option<String> = matches.opt_value_from_str(["-o", "--only"])?; |
156 | let with_deps: bool = matches.contains("--with-deps"); | 159 | let with_deps: bool = matches.contains("--with-deps"); |
160 | let load_output_dirs = matches.contains("--load-output-dirs"); | ||
157 | let path = { | 161 | let path = { |
158 | let mut trailing = matches.free()?; | 162 | let mut trailing = matches.free()?; |
159 | if trailing.len() != 1 { | 163 | if trailing.len() != 1 { |
@@ -162,7 +166,7 @@ ARGS: | |||
162 | trailing.pop().unwrap().into() | 166 | trailing.pop().unwrap().into() |
163 | }; | 167 | }; |
164 | 168 | ||
165 | Command::Stats { randomize, memory_usage, only, with_deps, path } | 169 | Command::Stats { randomize, memory_usage, only, with_deps, path, load_output_dirs } |
166 | } | 170 | } |
167 | "analysis-bench" => { | 171 | "analysis-bench" => { |
168 | if matches.contains(["-h", "--help"]) { | 172 | if matches.contains(["-h", "--help"]) { |
@@ -174,7 +178,8 @@ USAGE: | |||
174 | rust-analyzer analysis-bench [FLAGS] [OPTIONS] | 178 | rust-analyzer analysis-bench [FLAGS] [OPTIONS] |
175 | 179 | ||
176 | FLAGS: | 180 | FLAGS: |
177 | -h, --help Prints help information | 181 | -h, --help Prints help information |
182 | --load-output-dirs Load OUT_DIR values by running `cargo check` before analysis | ||
178 | -v, --verbose | 183 | -v, --verbose |
179 | 184 | ||
180 | OPTIONS: | 185 | OPTIONS: |
@@ -201,7 +206,8 @@ ARGS: | |||
201 | "exactly one of `--highlight`, `--complete` or `--goto-def` must be set" | 206 | "exactly one of `--highlight`, `--complete` or `--goto-def` must be set" |
202 | ), | 207 | ), |
203 | }; | 208 | }; |
204 | Command::Bench { path, what } | 209 | let load_output_dirs = matches.contains("--load-output-dirs"); |
210 | Command::Bench { path, what, load_output_dirs } | ||
205 | } | 211 | } |
206 | _ => { | 212 | _ => { |
207 | eprintln!( | 213 | eprintln!( |
diff --git a/crates/rust-analyzer/src/bin/main.rs b/crates/rust-analyzer/src/bin/main.rs index dd15b3458..a744a6695 100644 --- a/crates/rust-analyzer/src/bin/main.rs +++ b/crates/rust-analyzer/src/bin/main.rs | |||
@@ -19,19 +19,25 @@ fn main() -> Result<()> { | |||
19 | args::Command::Parse { no_dump } => cli::parse(no_dump)?, | 19 | args::Command::Parse { no_dump } => cli::parse(no_dump)?, |
20 | args::Command::Symbols => cli::symbols()?, | 20 | args::Command::Symbols => cli::symbols()?, |
21 | args::Command::Highlight { rainbow } => cli::highlight(rainbow)?, | 21 | args::Command::Highlight { rainbow } => cli::highlight(rainbow)?, |
22 | args::Command::Stats { randomize, memory_usage, only, with_deps, path } => { | 22 | args::Command::Stats { |
23 | cli::analysis_stats( | 23 | randomize, |
24 | args.verbosity, | 24 | memory_usage, |
25 | memory_usage, | 25 | only, |
26 | path.as_ref(), | 26 | with_deps, |
27 | only.as_ref().map(String::as_ref), | 27 | path, |
28 | with_deps, | 28 | load_output_dirs, |
29 | randomize, | 29 | } => cli::analysis_stats( |
30 | )? | 30 | args.verbosity, |
31 | } | 31 | memory_usage, |
32 | 32 | path.as_ref(), | |
33 | args::Command::Bench { path, what } => { | 33 | only.as_ref().map(String::as_ref), |
34 | cli::analysis_bench(args.verbosity, path.as_ref(), what)? | 34 | with_deps, |
35 | randomize, | ||
36 | load_output_dirs, | ||
37 | )?, | ||
38 | |||
39 | args::Command::Bench { path, what, load_output_dirs } => { | ||
40 | cli::analysis_bench(args.verbosity, path.as_ref(), what, load_output_dirs)? | ||
35 | } | 41 | } |
36 | 42 | ||
37 | args::Command::RunServer => run_server()?, | 43 | args::Command::RunServer => run_server()?, |
diff --git a/crates/rust-analyzer/src/cli/analysis_bench.rs b/crates/rust-analyzer/src/cli/analysis_bench.rs index 28a23934f..7164b0ade 100644 --- a/crates/rust-analyzer/src/cli/analysis_bench.rs +++ b/crates/rust-analyzer/src/cli/analysis_bench.rs | |||
@@ -42,12 +42,17 @@ fn rsplit_at_char(s: &str, c: char) -> Result<(&str, &str)> { | |||
42 | Ok((&s[..idx], &s[idx + 1..])) | 42 | Ok((&s[..idx], &s[idx + 1..])) |
43 | } | 43 | } |
44 | 44 | ||
45 | pub fn analysis_bench(verbosity: Verbosity, path: &Path, what: BenchWhat) -> Result<()> { | 45 | pub fn analysis_bench( |
46 | verbosity: Verbosity, | ||
47 | path: &Path, | ||
48 | what: BenchWhat, | ||
49 | load_output_dirs: bool, | ||
50 | ) -> Result<()> { | ||
46 | ra_prof::init(); | 51 | ra_prof::init(); |
47 | 52 | ||
48 | let start = Instant::now(); | 53 | let start = Instant::now(); |
49 | eprint!("loading: "); | 54 | eprint!("loading: "); |
50 | let (mut host, roots) = load_cargo(path)?; | 55 | let (mut host, roots) = load_cargo(path, load_output_dirs)?; |
51 | let db = host.raw_database(); | 56 | let db = host.raw_database(); |
52 | eprintln!("{:?}\n", start.elapsed()); | 57 | eprintln!("{:?}\n", start.elapsed()); |
53 | 58 | ||
diff --git a/crates/rust-analyzer/src/cli/analysis_stats.rs b/crates/rust-analyzer/src/cli/analysis_stats.rs index 643c54a9d..27459be8c 100644 --- a/crates/rust-analyzer/src/cli/analysis_stats.rs +++ b/crates/rust-analyzer/src/cli/analysis_stats.rs | |||
@@ -23,9 +23,10 @@ pub fn analysis_stats( | |||
23 | only: Option<&str>, | 23 | only: Option<&str>, |
24 | with_deps: bool, | 24 | with_deps: bool, |
25 | randomize: bool, | 25 | randomize: bool, |
26 | load_output_dirs: bool, | ||
26 | ) -> Result<()> { | 27 | ) -> Result<()> { |
27 | let db_load_time = Instant::now(); | 28 | let db_load_time = Instant::now(); |
28 | let (mut host, roots) = load_cargo(path)?; | 29 | let (mut host, roots) = load_cargo(path, load_output_dirs)?; |
29 | let db = host.raw_database(); | 30 | let db = host.raw_database(); |
30 | println!("Database loaded, {} roots, {:?}", roots.len(), db_load_time.elapsed()); | 31 | println!("Database loaded, {} roots, {:?}", roots.len(), db_load_time.elapsed()); |
31 | let analysis_time = Instant::now(); | 32 | let analysis_time = Instant::now(); |
diff --git a/crates/rust-analyzer/src/cli/load_cargo.rs b/crates/rust-analyzer/src/cli/load_cargo.rs index 2ce69c9b3..54e2fa1a7 100644 --- a/crates/rust-analyzer/src/cli/load_cargo.rs +++ b/crates/rust-analyzer/src/cli/load_cargo.rs | |||
@@ -1,13 +1,13 @@ | |||
1 | //! Loads a Cargo project into a static instance of analysis, without support | 1 | //! Loads a Cargo project into a static instance of analysis, without support |
2 | //! for incorporating changes. | 2 | //! for incorporating changes. |
3 | 3 | ||
4 | use std::path::Path; | 4 | use std::path::{Path, PathBuf}; |
5 | 5 | ||
6 | use anyhow::Result; | 6 | use anyhow::Result; |
7 | use crossbeam_channel::{unbounded, Receiver}; | 7 | use crossbeam_channel::{unbounded, Receiver}; |
8 | use ra_db::{CrateGraph, FileId, SourceRootId}; | 8 | use ra_db::{ExternSourceId, FileId, SourceRootId}; |
9 | use ra_ide::{AnalysisChange, AnalysisHost}; | 9 | use ra_ide::{AnalysisChange, AnalysisHost}; |
10 | use ra_project_model::{get_rustc_cfg_options, PackageRoot, ProjectWorkspace}; | 10 | use ra_project_model::{get_rustc_cfg_options, CargoFeatures, PackageRoot, ProjectWorkspace}; |
11 | use ra_vfs::{RootEntry, Vfs, VfsChange, VfsTask, Watch}; | 11 | use ra_vfs::{RootEntry, Vfs, VfsChange, VfsTask, Watch}; |
12 | use rustc_hash::{FxHashMap, FxHashSet}; | 12 | use rustc_hash::{FxHashMap, FxHashSet}; |
13 | 13 | ||
@@ -22,10 +22,21 @@ fn vfs_root_to_id(r: ra_vfs::VfsRoot) -> SourceRootId { | |||
22 | 22 | ||
23 | pub(crate) fn load_cargo( | 23 | pub(crate) fn load_cargo( |
24 | root: &Path, | 24 | root: &Path, |
25 | load_out_dirs_from_check: bool, | ||
25 | ) -> Result<(AnalysisHost, FxHashMap<SourceRootId, PackageRoot>)> { | 26 | ) -> Result<(AnalysisHost, FxHashMap<SourceRootId, PackageRoot>)> { |
26 | let root = std::env::current_dir()?.join(root); | 27 | let root = std::env::current_dir()?.join(root); |
27 | let ws = ProjectWorkspace::discover(root.as_ref(), &Default::default())?; | 28 | let ws = ProjectWorkspace::discover( |
28 | let project_roots = ws.to_roots(); | 29 | root.as_ref(), |
30 | &CargoFeatures { load_out_dirs_from_check, ..Default::default() }, | ||
31 | )?; | ||
32 | |||
33 | let mut extern_dirs = FxHashSet::default(); | ||
34 | extern_dirs.extend(ws.out_dirs()); | ||
35 | |||
36 | let mut project_roots = ws.to_roots(); | ||
37 | project_roots | ||
38 | .extend(extern_dirs.iter().map(|path| PackageRoot::new(path.to_path_buf(), false))); | ||
39 | |||
29 | let (sender, receiver) = unbounded(); | 40 | let (sender, receiver) = unbounded(); |
30 | let sender = Box::new(move |t| sender.send(t).unwrap()); | 41 | let sender = Box::new(move |t| sender.send(t).unwrap()); |
31 | let (mut vfs, roots) = Vfs::new( | 42 | let (mut vfs, roots) = Vfs::new( |
@@ -44,24 +55,6 @@ pub(crate) fn load_cargo( | |||
44 | Watch(false), | 55 | Watch(false), |
45 | ); | 56 | ); |
46 | 57 | ||
47 | // FIXME: cfg options? | ||
48 | let default_cfg_options = { | ||
49 | let mut opts = get_rustc_cfg_options(); | ||
50 | opts.insert_atom("test".into()); | ||
51 | opts.insert_atom("debug_assertion".into()); | ||
52 | opts | ||
53 | }; | ||
54 | |||
55 | // FIXME: outdirs? | ||
56 | let outdirs = FxHashMap::default(); | ||
57 | |||
58 | let crate_graph = ws.to_crate_graph(&default_cfg_options, &outdirs, &mut |path: &Path| { | ||
59 | let vfs_file = vfs.load(path); | ||
60 | log::debug!("vfs file {:?} -> {:?}", path, vfs_file); | ||
61 | vfs_file.map(vfs_file_to_id) | ||
62 | }); | ||
63 | log::debug!("crate graph: {:?}", crate_graph); | ||
64 | |||
65 | let source_roots = roots | 58 | let source_roots = roots |
66 | .iter() | 59 | .iter() |
67 | .map(|&vfs_root| { | 60 | .map(|&vfs_root| { |
@@ -74,23 +67,24 @@ pub(crate) fn load_cargo( | |||
74 | (source_root_id, project_root) | 67 | (source_root_id, project_root) |
75 | }) | 68 | }) |
76 | .collect::<FxHashMap<_, _>>(); | 69 | .collect::<FxHashMap<_, _>>(); |
77 | let host = load(&source_roots, crate_graph, &mut vfs, receiver); | 70 | let host = load(&source_roots, ws, &mut vfs, receiver, extern_dirs); |
78 | Ok((host, source_roots)) | 71 | Ok((host, source_roots)) |
79 | } | 72 | } |
80 | 73 | ||
81 | pub(crate) fn load( | 74 | pub(crate) fn load( |
82 | source_roots: &FxHashMap<SourceRootId, PackageRoot>, | 75 | source_roots: &FxHashMap<SourceRootId, PackageRoot>, |
83 | crate_graph: CrateGraph, | 76 | ws: ProjectWorkspace, |
84 | vfs: &mut Vfs, | 77 | vfs: &mut Vfs, |
85 | receiver: Receiver<VfsTask>, | 78 | receiver: Receiver<VfsTask>, |
79 | extern_dirs: FxHashSet<PathBuf>, | ||
86 | ) -> AnalysisHost { | 80 | ) -> AnalysisHost { |
87 | let lru_cap = std::env::var("RA_LRU_CAP").ok().and_then(|it| it.parse::<usize>().ok()); | 81 | let lru_cap = std::env::var("RA_LRU_CAP").ok().and_then(|it| it.parse::<usize>().ok()); |
88 | let mut host = AnalysisHost::new(lru_cap); | 82 | let mut host = AnalysisHost::new(lru_cap); |
89 | let mut analysis_change = AnalysisChange::new(); | 83 | let mut analysis_change = AnalysisChange::new(); |
90 | analysis_change.set_crate_graph(crate_graph); | ||
91 | 84 | ||
92 | // wait until Vfs has loaded all roots | 85 | // wait until Vfs has loaded all roots |
93 | let mut roots_loaded = FxHashSet::default(); | 86 | let mut roots_loaded = FxHashSet::default(); |
87 | let mut extern_source_roots = FxHashMap::default(); | ||
94 | for task in receiver { | 88 | for task in receiver { |
95 | vfs.handle_task(task); | 89 | vfs.handle_task(task); |
96 | let mut done = false; | 90 | let mut done = false; |
@@ -110,6 +104,11 @@ pub(crate) fn load( | |||
110 | source_roots[&source_root_id].path().display().to_string(), | 104 | source_roots[&source_root_id].path().display().to_string(), |
111 | ); | 105 | ); |
112 | 106 | ||
107 | let vfs_root_path = vfs.root2path(root); | ||
108 | if extern_dirs.contains(&vfs_root_path) { | ||
109 | extern_source_roots.insert(vfs_root_path, ExternSourceId(root.0)); | ||
110 | } | ||
111 | |||
113 | let mut file_map = FxHashMap::default(); | 112 | let mut file_map = FxHashMap::default(); |
114 | for (vfs_file, path, text) in files { | 113 | for (vfs_file, path, text) in files { |
115 | let file_id = vfs_file_to_id(vfs_file); | 114 | let file_id = vfs_file_to_id(vfs_file); |
@@ -136,6 +135,23 @@ pub(crate) fn load( | |||
136 | } | 135 | } |
137 | } | 136 | } |
138 | 137 | ||
138 | // FIXME: cfg options? | ||
139 | let default_cfg_options = { | ||
140 | let mut opts = get_rustc_cfg_options(); | ||
141 | opts.insert_atom("test".into()); | ||
142 | opts.insert_atom("debug_assertion".into()); | ||
143 | opts | ||
144 | }; | ||
145 | |||
146 | let crate_graph = | ||
147 | ws.to_crate_graph(&default_cfg_options, &extern_source_roots, &mut |path: &Path| { | ||
148 | let vfs_file = vfs.load(path); | ||
149 | log::debug!("vfs file {:?} -> {:?}", path, vfs_file); | ||
150 | vfs_file.map(vfs_file_to_id) | ||
151 | }); | ||
152 | log::debug!("crate graph: {:?}", crate_graph); | ||
153 | analysis_change.set_crate_graph(crate_graph); | ||
154 | |||
139 | host.apply_change(analysis_change); | 155 | host.apply_change(analysis_change); |
140 | host | 156 | host |
141 | } | 157 | } |
@@ -149,7 +165,7 @@ mod tests { | |||
149 | #[test] | 165 | #[test] |
150 | fn test_loading_rust_analyzer() { | 166 | fn test_loading_rust_analyzer() { |
151 | let path = Path::new(env!("CARGO_MANIFEST_DIR")).parent().unwrap().parent().unwrap(); | 167 | let path = Path::new(env!("CARGO_MANIFEST_DIR")).parent().unwrap().parent().unwrap(); |
152 | let (host, _roots) = load_cargo(path).unwrap(); | 168 | let (host, _roots) = load_cargo(path, false).unwrap(); |
153 | let n_crates = Crate::all(host.raw_database()).len(); | 169 | let n_crates = Crate::all(host.raw_database()).len(); |
154 | // RA has quite a few crates, but the exact count doesn't matter | 170 | // RA has quite a few crates, but the exact count doesn't matter |
155 | assert!(n_crates > 20); | 171 | assert!(n_crates > 20); |
diff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs index 6b9a11a87..103b2b53c 100644 --- a/crates/rust-analyzer/src/config.rs +++ b/crates/rust-analyzer/src/config.rs | |||
@@ -48,9 +48,6 @@ pub struct ServerConfig { | |||
48 | /// Fine grained feature flags to disable specific features. | 48 | /// Fine grained feature flags to disable specific features. |
49 | pub feature_flags: FxHashMap<String, bool>, | 49 | pub feature_flags: FxHashMap<String, bool>, |
50 | 50 | ||
51 | /// Fine grained controls for additional `OUT_DIR` env variables | ||
52 | pub additional_out_dirs: FxHashMap<String, String>, | ||
53 | |||
54 | pub rustfmt_args: Vec<String>, | 51 | pub rustfmt_args: Vec<String>, |
55 | 52 | ||
56 | /// Cargo feature configurations. | 53 | /// Cargo feature configurations. |
@@ -76,7 +73,6 @@ impl Default for ServerConfig { | |||
76 | cargo_watch_all_targets: true, | 73 | cargo_watch_all_targets: true, |
77 | with_sysroot: true, | 74 | with_sysroot: true, |
78 | feature_flags: FxHashMap::default(), | 75 | feature_flags: FxHashMap::default(), |
79 | additional_out_dirs: FxHashMap::default(), | ||
80 | cargo_features: Default::default(), | 76 | cargo_features: Default::default(), |
81 | rustfmt_args: Vec::new(), | 77 | rustfmt_args: Vec::new(), |
82 | vscode_lldb: false, | 78 | vscode_lldb: false, |
diff --git a/crates/rust-analyzer/src/main_loop.rs b/crates/rust-analyzer/src/main_loop.rs index 1fefc66aa..a8a5894d2 100644 --- a/crates/rust-analyzer/src/main_loop.rs +++ b/crates/rust-analyzer/src/main_loop.rs | |||
@@ -204,7 +204,6 @@ pub fn main_loop( | |||
204 | Watch(!config.use_client_watching), | 204 | Watch(!config.use_client_watching), |
205 | options, | 205 | options, |
206 | feature_flags, | 206 | feature_flags, |
207 | config.additional_out_dirs, | ||
208 | ) | 207 | ) |
209 | }; | 208 | }; |
210 | 209 | ||
diff --git a/crates/rust-analyzer/src/world.rs b/crates/rust-analyzer/src/world.rs index 5743471bf..c4244fee2 100644 --- a/crates/rust-analyzer/src/world.rs +++ b/crates/rust-analyzer/src/world.rs | |||
@@ -82,7 +82,6 @@ impl WorldState { | |||
82 | watch: Watch, | 82 | watch: Watch, |
83 | options: Options, | 83 | options: Options, |
84 | feature_flags: FeatureFlags, | 84 | feature_flags: FeatureFlags, |
85 | additional_out_dirs: FxHashMap<String, String>, | ||
86 | ) -> WorldState { | 85 | ) -> WorldState { |
87 | let mut change = AnalysisChange::new(); | 86 | let mut change = AnalysisChange::new(); |
88 | 87 | ||
@@ -105,11 +104,14 @@ impl WorldState { | |||
105 | })); | 104 | })); |
106 | } | 105 | } |
107 | 106 | ||
108 | let extern_dirs: FxHashSet<_> = | 107 | let mut extern_dirs = FxHashSet::default(); |
109 | additional_out_dirs.iter().map(|(_, path)| (PathBuf::from(path))).collect(); | 108 | for ws in workspaces.iter() { |
109 | extern_dirs.extend(ws.out_dirs()); | ||
110 | } | ||
111 | |||
110 | let mut extern_source_roots = FxHashMap::default(); | 112 | let mut extern_source_roots = FxHashMap::default(); |
111 | 113 | ||
112 | roots.extend(additional_out_dirs.iter().map(|(_, path)| { | 114 | roots.extend(extern_dirs.iter().map(|path| { |
113 | let mut filter = RustPackageFilterBuilder::default().set_member(false); | 115 | let mut filter = RustPackageFilterBuilder::default().set_member(false); |
114 | for glob in exclude_globs.iter() { | 116 | for glob in exclude_globs.iter() { |
115 | filter = filter.exclude(glob.clone()); | 117 | filter = filter.exclude(glob.clone()); |
@@ -148,17 +150,9 @@ impl WorldState { | |||
148 | vfs_file.map(|f| FileId(f.0)) | 150 | vfs_file.map(|f| FileId(f.0)) |
149 | }; | 151 | }; |
150 | 152 | ||
151 | let mut outdirs = FxHashMap::default(); | ||
152 | for (name, path) in additional_out_dirs { | ||
153 | let path = PathBuf::from(&path); | ||
154 | if let Some(id) = extern_source_roots.get(&path) { | ||
155 | outdirs.insert(name, (id.clone(), path.to_string_lossy().replace("\\", "/"))); | ||
156 | } | ||
157 | } | ||
158 | |||
159 | workspaces | 153 | workspaces |
160 | .iter() | 154 | .iter() |
161 | .map(|ws| ws.to_crate_graph(&default_cfg_options, &outdirs, &mut load)) | 155 | .map(|ws| ws.to_crate_graph(&default_cfg_options, &extern_source_roots, &mut load)) |
162 | .for_each(|graph| { | 156 | .for_each(|graph| { |
163 | crate_graph.extend(graph); | 157 | crate_graph.extend(graph); |
164 | }); | 158 | }); |