diff options
Diffstat (limited to 'crates/project_model/src/lib.rs')
-rw-r--r-- | crates/project_model/src/lib.rs | 245 |
1 files changed, 121 insertions, 124 deletions
diff --git a/crates/project_model/src/lib.rs b/crates/project_model/src/lib.rs index 2d65fc076..2d91939ce 100644 --- a/crates/project_model/src/lib.rs +++ b/crates/project_model/src/lib.rs | |||
@@ -39,11 +39,18 @@ pub enum ProjectWorkspace { | |||
39 | impl fmt::Debug for ProjectWorkspace { | 39 | impl fmt::Debug for ProjectWorkspace { |
40 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | 40 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
41 | match self { | 41 | match self { |
42 | ProjectWorkspace::Cargo { cargo, .. } => { | 42 | ProjectWorkspace::Cargo { cargo, sysroot } => f |
43 | f.debug_struct("Cargo").field("n_packages", &cargo.packages().len()).finish() | 43 | .debug_struct("Cargo") |
44 | } | 44 | .field("n_packages", &cargo.packages().len()) |
45 | .field("n_sysroot_crates", &sysroot.crates().len()) | ||
46 | .finish(), | ||
45 | ProjectWorkspace::Json { project } => { | 47 | ProjectWorkspace::Json { project } => { |
46 | f.debug_struct("Json").field("n_crates", &project.crates.len()).finish() | 48 | let mut debug_struct = f.debug_struct("Json"); |
49 | debug_struct.field("n_crates", &project.n_crates()); | ||
50 | if let Some(sysroot) = &project.sysroot { | ||
51 | debug_struct.field("n_sysroot_crates", &sysroot.crates().len()); | ||
52 | } | ||
53 | debug_struct.finish() | ||
47 | } | 54 | } |
48 | } | 55 | } |
49 | } | 56 | } |
@@ -202,15 +209,21 @@ impl ProjectWorkspace { | |||
202 | pub fn to_roots(&self) -> Vec<PackageRoot> { | 209 | pub fn to_roots(&self) -> Vec<PackageRoot> { |
203 | match self { | 210 | match self { |
204 | ProjectWorkspace::Json { project } => project | 211 | ProjectWorkspace::Json { project } => project |
205 | .crates | 212 | .crates() |
206 | .iter() | 213 | .map(|(_, krate)| PackageRoot { |
207 | .map(|krate| PackageRoot { | ||
208 | is_member: krate.is_workspace_member, | 214 | is_member: krate.is_workspace_member, |
209 | include: krate.include.clone(), | 215 | include: krate.include.clone(), |
210 | exclude: krate.exclude.clone(), | 216 | exclude: krate.exclude.clone(), |
211 | }) | 217 | }) |
212 | .collect::<FxHashSet<_>>() | 218 | .collect::<FxHashSet<_>>() |
213 | .into_iter() | 219 | .into_iter() |
220 | .chain(project.sysroot.as_ref().into_iter().flat_map(|sysroot| { | ||
221 | sysroot.crates().map(move |krate| PackageRoot { | ||
222 | is_member: false, | ||
223 | include: vec![sysroot[krate].root_dir().to_path_buf()], | ||
224 | exclude: Vec::new(), | ||
225 | }) | ||
226 | })) | ||
214 | .collect::<Vec<_>>(), | 227 | .collect::<Vec<_>>(), |
215 | ProjectWorkspace::Cargo { cargo, sysroot } => cargo | 228 | ProjectWorkspace::Cargo { cargo, sysroot } => cargo |
216 | .packages() | 229 | .packages() |
@@ -243,9 +256,8 @@ impl ProjectWorkspace { | |||
243 | pub fn proc_macro_dylib_paths(&self) -> Vec<AbsPathBuf> { | 256 | pub fn proc_macro_dylib_paths(&self) -> Vec<AbsPathBuf> { |
244 | match self { | 257 | match self { |
245 | ProjectWorkspace::Json { project } => project | 258 | ProjectWorkspace::Json { project } => project |
246 | .crates | 259 | .crates() |
247 | .iter() | 260 | .filter_map(|(_, krate)| krate.proc_macro_dylib_path.as_ref()) |
248 | .filter_map(|krate| krate.proc_macro_dylib_path.as_ref()) | ||
249 | .cloned() | 261 | .cloned() |
250 | .collect(), | 262 | .collect(), |
251 | ProjectWorkspace::Cargo { cargo, sysroot: _sysroot } => cargo | 263 | ProjectWorkspace::Cargo { cargo, sysroot: _sysroot } => cargo |
@@ -258,7 +270,7 @@ impl ProjectWorkspace { | |||
258 | 270 | ||
259 | pub fn n_packages(&self) -> usize { | 271 | pub fn n_packages(&self) -> usize { |
260 | match self { | 272 | match self { |
261 | ProjectWorkspace::Json { project, .. } => project.crates.len(), | 273 | ProjectWorkspace::Json { project, .. } => project.n_crates(), |
262 | ProjectWorkspace::Cargo { cargo, sysroot } => { | 274 | ProjectWorkspace::Cargo { cargo, sysroot } => { |
263 | cargo.packages().len() + sysroot.crates().len() | 275 | cargo.packages().len() + sysroot.crates().len() |
264 | } | 276 | } |
@@ -274,12 +286,15 @@ impl ProjectWorkspace { | |||
274 | let mut crate_graph = CrateGraph::default(); | 286 | let mut crate_graph = CrateGraph::default(); |
275 | match self { | 287 | match self { |
276 | ProjectWorkspace::Json { project } => { | 288 | ProjectWorkspace::Json { project } => { |
289 | let sysroot_dps = project | ||
290 | .sysroot | ||
291 | .as_ref() | ||
292 | .map(|sysroot| sysroot_to_crate_graph(&mut crate_graph, sysroot, target, load)); | ||
293 | |||
277 | let mut cfg_cache: FxHashMap<Option<&str>, Vec<CfgFlag>> = FxHashMap::default(); | 294 | let mut cfg_cache: FxHashMap<Option<&str>, Vec<CfgFlag>> = FxHashMap::default(); |
278 | let crates: FxHashMap<_, _> = project | 295 | let crates: FxHashMap<_, _> = project |
279 | .crates | 296 | .crates() |
280 | .iter() | 297 | .filter_map(|(crate_id, krate)| { |
281 | .enumerate() | ||
282 | .filter_map(|(seq_index, krate)| { | ||
283 | let file_path = &krate.root_module; | 298 | let file_path = &krate.root_module; |
284 | let file_id = load(&file_path)?; | 299 | let file_id = load(&file_path)?; |
285 | 300 | ||
@@ -297,9 +312,8 @@ impl ProjectWorkspace { | |||
297 | let mut cfg_options = CfgOptions::default(); | 312 | let mut cfg_options = CfgOptions::default(); |
298 | cfg_options.extend(target_cfgs.iter().chain(krate.cfg.iter()).cloned()); | 313 | cfg_options.extend(target_cfgs.iter().chain(krate.cfg.iter()).cloned()); |
299 | 314 | ||
300 | // FIXME: No crate name in json definition such that we cannot add OUT_DIR to env | ||
301 | Some(( | 315 | Some(( |
302 | CrateId(seq_index as u32), | 316 | crate_id, |
303 | crate_graph.add_crate_root( | 317 | crate_graph.add_crate_root( |
304 | file_id, | 318 | file_id, |
305 | krate.edition, | 319 | krate.edition, |
@@ -313,67 +327,33 @@ impl ProjectWorkspace { | |||
313 | }) | 327 | }) |
314 | .collect(); | 328 | .collect(); |
315 | 329 | ||
316 | for (id, krate) in project.crates.iter().enumerate() { | 330 | for (from, krate) in project.crates() { |
317 | for dep in &krate.deps { | 331 | if let Some(&from) = crates.get(&from) { |
318 | let from_crate_id = CrateId(id as u32); | 332 | if let Some((public_deps, _proc_macro)) = &sysroot_dps { |
319 | let to_crate_id = dep.crate_id; | 333 | for (name, to) in public_deps.iter() { |
320 | if let (Some(&from), Some(&to)) = | 334 | if let Err(_) = crate_graph.add_dep(from, name.clone(), *to) { |
321 | (crates.get(&from_crate_id), crates.get(&to_crate_id)) | 335 | log::error!("cyclic dependency on {} for {:?}", name, from) |
322 | { | 336 | } |
323 | if crate_graph.add_dep(from, dep.name.clone(), to).is_err() { | ||
324 | log::error!( | ||
325 | "cyclic dependency {:?} -> {:?}", | ||
326 | from_crate_id, | ||
327 | to_crate_id | ||
328 | ); | ||
329 | } | 337 | } |
330 | } | 338 | } |
331 | } | ||
332 | } | ||
333 | } | ||
334 | ProjectWorkspace::Cargo { cargo, sysroot } => { | ||
335 | let mut cfg_options = CfgOptions::default(); | ||
336 | cfg_options.extend(get_rustc_cfg_options(target)); | ||
337 | |||
338 | let sysroot_crates: FxHashMap<_, _> = sysroot | ||
339 | .crates() | ||
340 | .filter_map(|krate| { | ||
341 | let file_id = load(&sysroot[krate].root)?; | ||
342 | |||
343 | let env = Env::default(); | ||
344 | let proc_macro = vec![]; | ||
345 | let name = sysroot[krate].name.clone(); | ||
346 | let crate_id = crate_graph.add_crate_root( | ||
347 | file_id, | ||
348 | Edition::Edition2018, | ||
349 | Some(name), | ||
350 | cfg_options.clone(), | ||
351 | env, | ||
352 | proc_macro, | ||
353 | ); | ||
354 | Some((krate, crate_id)) | ||
355 | }) | ||
356 | .collect(); | ||
357 | 339 | ||
358 | for from in sysroot.crates() { | 340 | for dep in &krate.deps { |
359 | for &to in sysroot[from].deps.iter() { | 341 | let to_crate_id = dep.crate_id; |
360 | let name = &sysroot[to].name; | 342 | if let Some(&to) = crates.get(&to_crate_id) { |
361 | if let (Some(&from), Some(&to)) = | 343 | if let Err(_) = crate_graph.add_dep(from, dep.name.clone(), to) { |
362 | (sysroot_crates.get(&from), sysroot_crates.get(&to)) | 344 | log::error!("cyclic dependency {:?} -> {:?}", from, to); |
363 | { | 345 | } |
364 | if crate_graph.add_dep(from, CrateName::new(name).unwrap(), to).is_err() | ||
365 | { | ||
366 | log::error!("cyclic dependency between sysroot crates") | ||
367 | } | 346 | } |
368 | } | 347 | } |
369 | } | 348 | } |
370 | } | 349 | } |
350 | } | ||
351 | ProjectWorkspace::Cargo { cargo, sysroot } => { | ||
352 | let (public_deps, libproc_macro) = | ||
353 | sysroot_to_crate_graph(&mut crate_graph, sysroot, target, load); | ||
371 | 354 | ||
372 | let libcore = sysroot.core().and_then(|it| sysroot_crates.get(&it).copied()); | 355 | let mut cfg_options = CfgOptions::default(); |
373 | let liballoc = sysroot.alloc().and_then(|it| sysroot_crates.get(&it).copied()); | 356 | cfg_options.extend(get_rustc_cfg_options(target)); |
374 | let libstd = sysroot.std().and_then(|it| sysroot_crates.get(&it).copied()); | ||
375 | let libproc_macro = | ||
376 | sysroot.proc_macro().and_then(|it| sysroot_crates.get(&it).copied()); | ||
377 | 357 | ||
378 | let mut pkg_to_lib_crate = FxHashMap::default(); | 358 | let mut pkg_to_lib_crate = FxHashMap::default(); |
379 | let mut pkg_crates = FxHashMap::default(); | 359 | let mut pkg_crates = FxHashMap::default(); |
@@ -424,14 +404,11 @@ impl ProjectWorkspace { | |||
424 | } | 404 | } |
425 | if cargo[tgt].is_proc_macro { | 405 | if cargo[tgt].is_proc_macro { |
426 | if let Some(proc_macro) = libproc_macro { | 406 | if let Some(proc_macro) = libproc_macro { |
427 | if crate_graph | 407 | if let Err(_) = crate_graph.add_dep( |
428 | .add_dep( | 408 | crate_id, |
429 | crate_id, | 409 | CrateName::new("proc_macro").unwrap(), |
430 | CrateName::new("proc_macro").unwrap(), | 410 | proc_macro, |
431 | proc_macro, | 411 | ) { |
432 | ) | ||
433 | .is_err() | ||
434 | { | ||
435 | log::error!( | 412 | log::error!( |
436 | "cyclic dependency on proc_macro for {}", | 413 | "cyclic dependency on proc_macro for {}", |
437 | &cargo[pkg].name | 414 | &cargo[pkg].name |
@@ -447,50 +424,24 @@ impl ProjectWorkspace { | |||
447 | // Set deps to the core, std and to the lib target of the current package | 424 | // Set deps to the core, std and to the lib target of the current package |
448 | for &from in pkg_crates.get(&pkg).into_iter().flatten() { | 425 | for &from in pkg_crates.get(&pkg).into_iter().flatten() { |
449 | if let Some((to, name)) = lib_tgt.clone() { | 426 | if let Some((to, name)) = lib_tgt.clone() { |
450 | if to != from | 427 | // For root projects with dashes in their name, |
451 | && crate_graph | 428 | // cargo metadata does not do any normalization, |
452 | .add_dep( | 429 | // so we do it ourselves currently |
453 | from, | 430 | let name = CrateName::normalize_dashes(&name); |
454 | // For root projects with dashes in their name, | 431 | if to != from && crate_graph.add_dep(from, name, to).is_err() { |
455 | // cargo metadata does not do any normalization, | 432 | log::error!( |
456 | // so we do it ourselves currently | 433 | "cyclic dependency between targets of {}", |
457 | CrateName::normalize_dashes(&name), | 434 | &cargo[pkg].name |
458 | to, | 435 | ) |
459 | ) | ||
460 | .is_err() | ||
461 | { | ||
462 | { | ||
463 | log::error!( | ||
464 | "cyclic dependency between targets of {}", | ||
465 | &cargo[pkg].name | ||
466 | ) | ||
467 | } | ||
468 | } | ||
469 | } | ||
470 | // core is added as a dependency before std in order to | ||
471 | // mimic rustcs dependency order | ||
472 | if let Some(core) = libcore { | ||
473 | if crate_graph | ||
474 | .add_dep(from, CrateName::new("core").unwrap(), core) | ||
475 | .is_err() | ||
476 | { | ||
477 | log::error!("cyclic dependency on core for {}", &cargo[pkg].name) | ||
478 | } | ||
479 | } | ||
480 | if let Some(alloc) = liballoc { | ||
481 | if crate_graph | ||
482 | .add_dep(from, CrateName::new("alloc").unwrap(), alloc) | ||
483 | .is_err() | ||
484 | { | ||
485 | log::error!("cyclic dependency on alloc for {}", &cargo[pkg].name) | ||
486 | } | 436 | } |
487 | } | 437 | } |
488 | if let Some(std) = libstd { | 438 | for (name, krate) in public_deps.iter() { |
489 | if crate_graph | 439 | if let Err(_) = crate_graph.add_dep(from, name.clone(), *krate) { |
490 | .add_dep(from, CrateName::new("std").unwrap(), std) | 440 | log::error!( |
491 | .is_err() | 441 | "cyclic dependency on {} for {}", |
492 | { | 442 | name, |
493 | log::error!("cyclic dependency on std for {}", &cargo[pkg].name) | 443 | &cargo[pkg].name |
444 | ) | ||
494 | } | 445 | } |
495 | } | 446 | } |
496 | } | 447 | } |
@@ -500,12 +451,10 @@ impl ProjectWorkspace { | |||
500 | // target of downstream. | 451 | // target of downstream. |
501 | for pkg in cargo.packages() { | 452 | for pkg in cargo.packages() { |
502 | for dep in cargo[pkg].dependencies.iter() { | 453 | for dep in cargo[pkg].dependencies.iter() { |
454 | let name = CrateName::new(&dep.name).unwrap(); | ||
503 | if let Some(&to) = pkg_to_lib_crate.get(&dep.pkg) { | 455 | if let Some(&to) = pkg_to_lib_crate.get(&dep.pkg) { |
504 | for &from in pkg_crates.get(&pkg).into_iter().flatten() { | 456 | for &from in pkg_crates.get(&pkg).into_iter().flatten() { |
505 | if crate_graph | 457 | if let Err(_) = crate_graph.add_dep(from, name.clone(), to) { |
506 | .add_dep(from, CrateName::new(&dep.name).unwrap(), to) | ||
507 | .is_err() | ||
508 | { | ||
509 | log::error!( | 458 | log::error!( |
510 | "cyclic dependency {} -> {}", | 459 | "cyclic dependency {} -> {}", |
511 | &cargo[pkg].name, | 460 | &cargo[pkg].name, |
@@ -563,3 +512,51 @@ fn utf8_stdout(mut cmd: Command) -> Result<String> { | |||
563 | let stdout = String::from_utf8(output.stdout)?; | 512 | let stdout = String::from_utf8(output.stdout)?; |
564 | Ok(stdout.trim().to_string()) | 513 | Ok(stdout.trim().to_string()) |
565 | } | 514 | } |
515 | |||
516 | fn sysroot_to_crate_graph( | ||
517 | crate_graph: &mut CrateGraph, | ||
518 | sysroot: &Sysroot, | ||
519 | target: Option<&str>, | ||
520 | load: &mut dyn FnMut(&AbsPath) -> Option<FileId>, | ||
521 | ) -> (Vec<(CrateName, CrateId)>, Option<CrateId>) { | ||
522 | let mut cfg_options = CfgOptions::default(); | ||
523 | cfg_options.extend(get_rustc_cfg_options(target)); | ||
524 | let sysroot_crates: FxHashMap<_, _> = sysroot | ||
525 | .crates() | ||
526 | .filter_map(|krate| { | ||
527 | let file_id = load(&sysroot[krate].root)?; | ||
528 | |||
529 | let env = Env::default(); | ||
530 | let proc_macro = vec![]; | ||
531 | let name = sysroot[krate].name.clone(); | ||
532 | let crate_id = crate_graph.add_crate_root( | ||
533 | file_id, | ||
534 | Edition::Edition2018, | ||
535 | Some(name), | ||
536 | cfg_options.clone(), | ||
537 | env, | ||
538 | proc_macro, | ||
539 | ); | ||
540 | Some((krate, crate_id)) | ||
541 | }) | ||
542 | .collect(); | ||
543 | |||
544 | for from in sysroot.crates() { | ||
545 | for &to in sysroot[from].deps.iter() { | ||
546 | let name = CrateName::new(&sysroot[to].name).unwrap(); | ||
547 | if let (Some(&from), Some(&to)) = (sysroot_crates.get(&from), sysroot_crates.get(&to)) { | ||
548 | if let Err(_) = crate_graph.add_dep(from, name, to) { | ||
549 | log::error!("cyclic dependency between sysroot crates") | ||
550 | } | ||
551 | } | ||
552 | } | ||
553 | } | ||
554 | |||
555 | let public_deps = sysroot | ||
556 | .public_deps() | ||
557 | .map(|(name, idx)| (CrateName::new(name).unwrap(), sysroot_crates[&idx])) | ||
558 | .collect::<Vec<_>>(); | ||
559 | |||
560 | let libproc_macro = sysroot.proc_macro().and_then(|it| sysroot_crates.get(&it).copied()); | ||
561 | (public_deps, libproc_macro) | ||
562 | } | ||