Skip to content

Commit b7afb6f

Browse files
bors[bot]Jonas Schievink
and
Jonas Schievink
authored
Merge #10958
10958: internal: add "Shuffle Crate Graph" command r=jonas-schievink a=jonas-schievink May be useful for debugging issues like #10084 bors r+ Co-authored-by: Jonas Schievink <[email protected]>
2 parents bf484d9 + 0db5aac commit b7afb6f

File tree

11 files changed

+115
-1
lines changed

11 files changed

+115
-1
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,4 @@ generated_diagnostic.adoc
1313
.DS_Store
1414
/out/
1515
/dump.lsif
16+
.envrc

crates/ide/src/lib.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ mod typing;
5656
mod view_crate_graph;
5757
mod view_hir;
5858
mod view_item_tree;
59+
mod shuffle_crate_graph;
5960

6061
use std::sync::Arc;
6162

@@ -177,6 +178,10 @@ impl AnalysisHost {
177178
pub fn raw_database_mut(&mut self) -> &mut RootDatabase {
178179
&mut self.db
179180
}
181+
182+
pub fn shuffle_crate_graph(&mut self) {
183+
shuffle_crate_graph::shuffle_crate_graph(&mut self.db);
184+
}
180185
}
181186

182187
impl Default for AnalysisHost {

crates/ide/src/shuffle_crate_graph.rs

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
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+
}

crates/rust-analyzer/src/handlers.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,11 @@ pub(crate) fn handle_memory_usage(state: &mut GlobalState, _: ()) -> Result<Stri
9797
Ok(out)
9898
}
9999

100+
pub(crate) fn handle_shuffle_crate_graph(state: &mut GlobalState, _: ()) -> Result<()> {
101+
state.analysis_host.shuffle_crate_graph();
102+
Ok(())
103+
}
104+
100105
pub(crate) fn handle_syntax_tree(
101106
snap: GlobalStateSnapshot,
102107
params: lsp_ext::SyntaxTreeParams,

crates/rust-analyzer/src/lsp_ext.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,14 @@ impl Request for MemoryUsage {
3131
const METHOD: &'static str = "rust-analyzer/memoryUsage";
3232
}
3333

34+
pub enum ShuffleCrateGraph {}
35+
36+
impl Request for ShuffleCrateGraph {
37+
type Params = ();
38+
type Result = ();
39+
const METHOD: &'static str = "rust-analyzer/shuffleCrateGraph";
40+
}
41+
3442
pub enum ReloadWorkspace {}
3543

3644
impl Request for ReloadWorkspace {

crates/rust-analyzer/src/main_loop.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -567,6 +567,7 @@ impl GlobalState {
567567
Ok(())
568568
})?
569569
.on_sync_mut::<lsp_ext::MemoryUsage>(handlers::handle_memory_usage)?
570+
.on_sync_mut::<lsp_ext::ShuffleCrateGraph>(handlers::handle_shuffle_crate_graph)?
570571
.on_sync::<lsp_ext::JoinLines>(handlers::handle_join_lines)?
571572
.on_sync::<lsp_ext::OnEnter>(handlers::handle_on_enter)?
572573
.on_sync::<lsp_types::request::SelectionRangeRequest>(handlers::handle_selection_range)?

docs/dev/lsp-extensions.md

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<!---
2-
lsp_ext.rs hash: c6568e4035333f3a
2+
lsp_ext.rs hash: 49ffd619919ed74
33
44
If you need to change the above hash to make the test pass, please check if you
55
need to adjust this doc as well and ping this issue:
@@ -526,6 +526,14 @@ Renders rust-analyzer's crate graph as an SVG image.
526526

527527
If `full` is `true`, the graph includes non-workspace crates (crates.io dependencies as well as sysroot crates).
528528

529+
## Shuffle Crate Graph
530+
531+
**Method:** `rust-analyzer/shuffleCrateGraph`
532+
533+
**Request:** `null`
534+
535+
Shuffles the crate IDs in the crate graph, for debugging purposes.
536+
529537
## Expand Macro
530538

531539
**Method:** `rust-analyzer/expandMacro`

editors/code/package.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,11 @@
171171
"title": "Memory Usage (Clears Database)",
172172
"category": "Rust Analyzer"
173173
},
174+
{
175+
"command": "rust-analyzer.shuffleCrateGraph",
176+
"title": "Shuffle Crate Graph",
177+
"category": "Rust Analyzer"
178+
},
174179
{
175180
"command": "rust-analyzer.reloadWorkspace",
176181
"title": "Reload workspace",

editors/code/src/commands.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,15 @@ export function memoryUsage(ctx: Ctx): Cmd {
8585
};
8686
}
8787

88+
export function shuffleCrateGraph(ctx: Ctx): Cmd {
89+
return async () => {
90+
const client = ctx.client;
91+
if (!client) return;
92+
93+
await client.sendRequest(ra.shuffleCrateGraph);
94+
};
95+
}
96+
8897
export function matchingBrace(ctx: Ctx): Cmd {
8998
return async () => {
9099
const editor = ctx.activeRustEditor;

editors/code/src/lsp_ext.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ export interface AnalyzerStatusParams {
99
}
1010
export const analyzerStatus = new lc.RequestType<AnalyzerStatusParams, string, void>("rust-analyzer/analyzerStatus");
1111
export const memoryUsage = new lc.RequestType0<string, void>("rust-analyzer/memoryUsage");
12+
export const shuffleCrateGraph = new lc.RequestType0<null, void>("rust-analyzer/shuffleCrateGraph");
1213

1314
export interface ServerStatusParams {
1415
health: "ok" | "warning" | "error";

editors/code/src/main.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,7 @@ async function initCommonContext(context: vscode.ExtensionContext, ctx: Ctx) {
117117

118118
ctx.registerCommand('analyzerStatus', commands.analyzerStatus);
119119
ctx.registerCommand('memoryUsage', commands.memoryUsage);
120+
ctx.registerCommand('shuffleCrateGraph', commands.shuffleCrateGraph);
120121
ctx.registerCommand('reloadWorkspace', commands.reloadWorkspace);
121122
ctx.registerCommand('matchingBrace', commands.matchingBrace);
122123
ctx.registerCommand('joinLines', commands.joinLines);

0 commit comments

Comments
 (0)