]> git.lizzy.rs Git - rust.git/blob - crates/ide/src/shuffle_crate_graph.rs
Merge #11579
[rust.git] / crates / ide / src / shuffle_crate_graph.rs
1 use std::sync::Arc;
2
3 use ide_db::base_db::salsa::Durability;
4 use ide_db::base_db::{CrateGraph, SourceDatabase};
5 use ide_db::RootDatabase;
6 use rustc_hash::FxHashMap;
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.origin.clone(),
38         );
39         map.insert(old_id, new_id);
40     }
41
42     for old_id in shuffled_ids.iter().copied() {
43         let data = &crate_graph[old_id];
44         for dep in &data.dependencies {
45             let mut new_dep = dep.clone();
46             new_dep.crate_id = map[&dep.crate_id];
47             new_graph.add_dep(map[&old_id], new_dep).unwrap();
48         }
49     }
50
51     db.set_crate_graph_with_durability(Arc::new(new_graph), Durability::HIGH);
52 }
53
54 fn shuffle<T>(slice: &mut [T]) {
55     let mut rng = oorandom::Rand32::new(seed());
56
57     let mut remaining = slice.len() - 1;
58     while remaining > 0 {
59         let index = rng.rand_range(0..remaining as u32);
60         slice.swap(remaining, index as usize);
61         remaining -= 1;
62     }
63 }
64
65 fn seed() -> u64 {
66     use std::collections::hash_map::RandomState;
67     use std::hash::{BuildHasher, Hasher};
68
69     RandomState::new().build_hasher().finish()
70 }