Unnamed repository; edit this file 'description' to name the repository.
Merge #10958
10958: internal: add "Shuffle Crate Graph" command r=jonas-schievink a=jonas-schievink May be useful for debugging issues like https://github.com/rust-analyzer/rust-analyzer/issues/10084 bors r+ Co-authored-by: Jonas Schievink <[email protected]>
bors[bot] 2021-12-07
parent bf484d9 · parent 0db5aac · commit b7afb6f
-rw-r--r--.gitignore1
-rw-r--r--crates/ide/src/lib.rs5
-rw-r--r--crates/ide/src/shuffle_crate_graph.rs70
-rw-r--r--crates/rust-analyzer/src/handlers.rs5
-rw-r--r--crates/rust-analyzer/src/lsp_ext.rs8
-rw-r--r--crates/rust-analyzer/src/main_loop.rs1
-rw-r--r--docs/dev/lsp-extensions.md10
-rw-r--r--editors/code/package.json5
-rw-r--r--editors/code/src/commands.ts9
-rw-r--r--editors/code/src/lsp_ext.ts1
-rw-r--r--editors/code/src/main.ts1
11 files changed, 115 insertions, 1 deletions
diff --git a/.gitignore b/.gitignore
index f3e3cab1d6..68c87a6b1e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -13,3 +13,4 @@ generated_diagnostic.adoc
.DS_Store
/out/
/dump.lsif
+.envrc
diff --git a/crates/ide/src/lib.rs b/crates/ide/src/lib.rs
index e7feb042b2..5bd9f054dd 100644
--- a/crates/ide/src/lib.rs
+++ b/crates/ide/src/lib.rs
@@ -56,6 +56,7 @@ mod typing;
mod view_crate_graph;
mod view_hir;
mod view_item_tree;
+mod shuffle_crate_graph;
use std::sync::Arc;
@@ -177,6 +178,10 @@ impl AnalysisHost {
pub fn raw_database_mut(&mut self) -> &mut RootDatabase {
&mut self.db
}
+
+ pub fn shuffle_crate_graph(&mut self) {
+ shuffle_crate_graph::shuffle_crate_graph(&mut self.db);
+ }
}
impl Default for AnalysisHost {
diff --git a/crates/ide/src/shuffle_crate_graph.rs b/crates/ide/src/shuffle_crate_graph.rs
new file mode 100644
index 0000000000..9c3cce5dfe
--- /dev/null
+++ b/crates/ide/src/shuffle_crate_graph.rs
@@ -0,0 +1,70 @@
+use std::sync::Arc;
+
+use ide_db::base_db::salsa::Durability;
+use ide_db::base_db::{CrateGraph, SourceDatabase};
+use ide_db::RootDatabase;
+use rustc_hash::FxHashMap;
+
+// Feature: Shuffle Crate Graph
+//
+// Randomizes all crate IDs in the crate graph, for debugging.
+//
+// |===
+// | Editor | Action Name
+//
+// | VS Code | **Rust Analyzer: Shuffle Crate Graph**
+// |===
+pub(crate) fn shuffle_crate_graph(db: &mut RootDatabase) {
+ let crate_graph = db.crate_graph();
+
+ let mut shuffled_ids = crate_graph.iter().collect::<Vec<_>>();
+ shuffle(&mut shuffled_ids);
+
+ let mut new_graph = CrateGraph::default();
+
+ let mut map = FxHashMap::default();
+ for old_id in shuffled_ids.iter().copied() {
+ let data = &crate_graph[old_id];
+ let new_id = new_graph.add_crate_root(
+ data.root_file_id,
+ data.edition,
+ data.display_name.clone(),
+ data.version.clone(),
+ data.cfg_options.clone(),
+ data.potential_cfg_options.clone(),
+ data.env.clone(),
+ data.proc_macro.clone(),
+ data.origin.clone(),
+ );
+ map.insert(old_id, new_id);
+ }
+
+ for old_id in shuffled_ids.iter().copied() {
+ let data = &crate_graph[old_id];
+ for dep in &data.dependencies {
+ let mut new_dep = dep.clone();
+ new_dep.crate_id = map[&dep.crate_id];
+ new_graph.add_dep(map[&old_id], new_dep).unwrap();
+ }
+ }
+
+ db.set_crate_graph_with_durability(Arc::new(new_graph), Durability::HIGH);
+}
+
+fn shuffle<T>(slice: &mut [T]) {
+ let mut rng = oorandom::Rand32::new(seed());
+
+ let mut remaining = slice.len() - 1;
+ while remaining > 0 {
+ let index = rng.rand_range(0..remaining as u32);
+ slice.swap(remaining, index as usize);
+ remaining -= 1;
+ }
+}
+
+fn seed() -> u64 {
+ use std::collections::hash_map::RandomState;
+ use std::hash::{BuildHasher, Hasher};
+
+ RandomState::new().build_hasher().finish()
+}
diff --git a/crates/rust-analyzer/src/handlers.rs b/crates/rust-analyzer/src/handlers.rs
index bf153012d9..ab3c9e8227 100644
--- a/crates/rust-analyzer/src/handlers.rs
+++ b/crates/rust-analyzer/src/handlers.rs
@@ -97,6 +97,11 @@ pub(crate) fn handle_memory_usage(state: &mut GlobalState, _: ()) -> Result<Stri
Ok(out)
}
+pub(crate) fn handle_shuffle_crate_graph(state: &mut GlobalState, _: ()) -> Result<()> {
+ state.analysis_host.shuffle_crate_graph();
+ Ok(())
+}
+
pub(crate) fn handle_syntax_tree(
snap: GlobalStateSnapshot,
params: lsp_ext::SyntaxTreeParams,
diff --git a/crates/rust-analyzer/src/lsp_ext.rs b/crates/rust-analyzer/src/lsp_ext.rs
index 19137b942e..0e23094199 100644
--- a/crates/rust-analyzer/src/lsp_ext.rs
+++ b/crates/rust-analyzer/src/lsp_ext.rs
@@ -31,6 +31,14 @@ impl Request for MemoryUsage {
const METHOD: &'static str = "rust-analyzer/memoryUsage";
}
+pub enum ShuffleCrateGraph {}
+
+impl Request for ShuffleCrateGraph {
+ type Params = ();
+ type Result = ();
+ const METHOD: &'static str = "rust-analyzer/shuffleCrateGraph";
+}
+
pub enum ReloadWorkspace {}
impl Request for ReloadWorkspace {
diff --git a/crates/rust-analyzer/src/main_loop.rs b/crates/rust-analyzer/src/main_loop.rs
index 2d83cbee66..65f9c87367 100644
--- a/crates/rust-analyzer/src/main_loop.rs
+++ b/crates/rust-analyzer/src/main_loop.rs
@@ -567,6 +567,7 @@ impl GlobalState {
Ok(())
})?
.on_sync_mut::<lsp_ext::MemoryUsage>(handlers::handle_memory_usage)?
+ .on_sync_mut::<lsp_ext::ShuffleCrateGraph>(handlers::handle_shuffle_crate_graph)?
.on_sync::<lsp_ext::JoinLines>(handlers::handle_join_lines)?
.on_sync::<lsp_ext::OnEnter>(handlers::handle_on_enter)?
.on_sync::<lsp_types::request::SelectionRangeRequest>(handlers::handle_selection_range)?
diff --git a/docs/dev/lsp-extensions.md b/docs/dev/lsp-extensions.md
index b925f146a7..c92395553c 100644
--- a/docs/dev/lsp-extensions.md
+++ b/docs/dev/lsp-extensions.md
@@ -1,5 +1,5 @@
<!---
-lsp_ext.rs hash: c6568e4035333f3a
+lsp_ext.rs hash: 49ffd619919ed74
If you need to change the above hash to make the test pass, please check if you
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.
If `full` is `true`, the graph includes non-workspace crates (crates.io dependencies as well as sysroot crates).
+## Shuffle Crate Graph
+
+**Method:** `rust-analyzer/shuffleCrateGraph`
+
+**Request:** `null`
+
+Shuffles the crate IDs in the crate graph, for debugging purposes.
+
## Expand Macro
**Method:** `rust-analyzer/expandMacro`
diff --git a/editors/code/package.json b/editors/code/package.json
index da4fa15b02..4b6e5ef333 100644
--- a/editors/code/package.json
+++ b/editors/code/package.json
@@ -172,6 +172,11 @@
"category": "Rust Analyzer"
},
{
+ "command": "rust-analyzer.shuffleCrateGraph",
+ "title": "Shuffle Crate Graph",
+ "category": "Rust Analyzer"
+ },
+ {
"command": "rust-analyzer.reloadWorkspace",
"title": "Reload workspace",
"category": "Rust Analyzer"
diff --git a/editors/code/src/commands.ts b/editors/code/src/commands.ts
index c9385361f8..fe006a63e2 100644
--- a/editors/code/src/commands.ts
+++ b/editors/code/src/commands.ts
@@ -85,6 +85,15 @@ export function memoryUsage(ctx: Ctx): Cmd {
};
}
+export function shuffleCrateGraph(ctx: Ctx): Cmd {
+ return async () => {
+ const client = ctx.client;
+ if (!client) return;
+
+ await client.sendRequest(ra.shuffleCrateGraph);
+ };
+}
+
export function matchingBrace(ctx: Ctx): Cmd {
return async () => {
const editor = ctx.activeRustEditor;
diff --git a/editors/code/src/lsp_ext.ts b/editors/code/src/lsp_ext.ts
index 90796e611e..a21a742a57 100644
--- a/editors/code/src/lsp_ext.ts
+++ b/editors/code/src/lsp_ext.ts
@@ -9,6 +9,7 @@ export interface AnalyzerStatusParams {
}
export const analyzerStatus = new lc.RequestType<AnalyzerStatusParams, string, void>("rust-analyzer/analyzerStatus");
export const memoryUsage = new lc.RequestType0<string, void>("rust-analyzer/memoryUsage");
+export const shuffleCrateGraph = new lc.RequestType0<null, void>("rust-analyzer/shuffleCrateGraph");
export interface ServerStatusParams {
health: "ok" | "warning" | "error";
diff --git a/editors/code/src/main.ts b/editors/code/src/main.ts
index 734f224503..a06fc09fc8 100644
--- a/editors/code/src/main.ts
+++ b/editors/code/src/main.ts
@@ -117,6 +117,7 @@ async function initCommonContext(context: vscode.ExtensionContext, ctx: Ctx) {
ctx.registerCommand('analyzerStatus', commands.analyzerStatus);
ctx.registerCommand('memoryUsage', commands.memoryUsage);
+ ctx.registerCommand('shuffleCrateGraph', commands.shuffleCrateGraph);
ctx.registerCommand('reloadWorkspace', commands.reloadWorkspace);
ctx.registerCommand('matchingBrace', commands.matchingBrace);
ctx.registerCommand('joinLines', commands.joinLines);