]> git.lizzy.rs Git - rust.git/blob - src/tools/rust-analyzer/crates/ide/src/shuffle_crate_graph.rs
Rollup merge of #99714 - ouz-a:issue_57961, r=oli-obk
[rust.git] / src / tools / rust-analyzer / crates / ide / src / shuffle_crate_graph.rs
1 use std::sync::Arc;
2
3 use ide_db::{
4     base_db::{salsa::Durability, CrateGraph, SourceDatabase},
5     FxHashMap, RootDatabase,
6 };
7
8 // Feature: Shuffle Crate Graph
9 //
10 // Randomizes all crate IDs in the crate graph, for debugging.
11 //
12 // |===
13 // | Editor  | Action Name
14 //
15 // | VS Code | **Rust Analyzer: Shuffle Crate Graph**
16 // |===
17 pub(crate) fn shuffle_crate_graph(db: &mut RootDatabase) {
18     let crate_graph = db.crate_graph();
19
20     let mut shuffled_ids = crate_graph.iter().collect::<Vec<_>>();
21     shuffle(&mut shuffled_ids);
22
23     let mut new_graph = CrateGraph::default();
24
25     let mut map = FxHashMap::default();
26     for old_id in shuffled_ids.iter().copied() {
27         let data = &crate_graph[old_id];
28         let new_id = new_graph.add_crate_root(
29             data.root_file_id,
30             data.edition,
31             data.display_name.clone(),
32             data.version.clone(),
33             data.cfg_options.clone(),
34             data.potential_cfg_options.clone(),
35             data.env.clone(),
36             data.proc_macro.clone(),
37             data.is_proc_macro,
38             data.origin.clone(),
39         );
40         map.insert(old_id, new_id);
41     }
42
43     for old_id in shuffled_ids.iter().copied() {
44         let data = &crate_graph[old_id];
45         for dep in &data.dependencies {
46             let mut new_dep = dep.clone();
47             new_dep.crate_id = map[&dep.crate_id];
48             new_graph.add_dep(map[&old_id], new_dep).unwrap();
49         }
50     }
51
52     db.set_crate_graph_with_durability(Arc::new(new_graph), Durability::HIGH);
53 }
54
55 fn shuffle<T>(slice: &mut [T]) {
56     let mut rng = oorandom::Rand32::new(seed());
57
58     let mut remaining = slice.len() - 1;
59     while remaining > 0 {
60         let index = rng.rand_range(0..remaining as u32);
61         slice.swap(remaining, index as usize);
62         remaining -= 1;
63     }
64 }
65
66 fn seed() -> u64 {
67     use std::collections::hash_map::RandomState;
68     use std::hash::{BuildHasher, Hasher};
69
70     RandomState::new().build_hasher().finish()
71 }