about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--crates/ide/src/lib.rs4
-rw-r--r--crates/ide/src/status.rs49
-rw-r--r--crates/rust-analyzer/src/handlers.rs19
-rw-r--r--crates/rust-analyzer/src/lsp_ext.rs8
-rw-r--r--docs/dev/lsp-extensions.md9
-rw-r--r--docs/user/manual.adoc4
-rw-r--r--editors/code/src/commands.ts19
-rw-r--r--editors/code/src/lsp_ext.ts5
8 files changed, 85 insertions, 32 deletions
diff --git a/crates/ide/src/lib.rs b/crates/ide/src/lib.rs
index 96dae9ee0bc..6d5fd1a557e 100644
--- a/crates/ide/src/lib.rs
+++ b/crates/ide/src/lib.rs
@@ -216,8 +216,8 @@ impl Analysis {
     }
 
     /// Debug info about the current state of the analysis.
-    pub fn status(&self) -> Cancelable<String> {
-        self.with_db(|db| status::status(&*db))
+    pub fn status(&self, file_id: Option<FileId>) -> Cancelable<String> {
+        self.with_db(|db| status::status(&*db, file_id))
     }
 
     pub fn prime_caches(&self, files: Vec<FileId>) -> Cancelable<()> {
diff --git a/crates/ide/src/status.rs b/crates/ide/src/status.rs
index 1427c50cf8e..0af84daa0a7 100644
--- a/crates/ide/src/status.rs
+++ b/crates/ide/src/status.rs
@@ -2,19 +2,19 @@ use std::{fmt, iter::FromIterator, sync::Arc};
 
 use base_db::{
     salsa::debug::{DebugQueryTable, TableEntry},
-    FileTextQuery, SourceRootId,
+    CrateId, FileId, FileTextQuery, SourceDatabase, SourceRootId,
 };
 use hir::MacroFile;
 use ide_db::{
     symbol_index::{LibrarySymbolsQuery, SymbolIndex},
     RootDatabase,
 };
+use itertools::Itertools;
 use profile::{memory_usage, Bytes};
 use rustc_hash::FxHashMap;
+use stdx::format_to;
 use syntax::{ast, Parse, SyntaxNode};
 
-use crate::FileId;
-
 fn syntax_tree_stats(db: &RootDatabase) -> SyntaxTreeStats {
     base_db::ParseQuery.in_db(db).entries::<SyntaxTreeStats>()
 }
@@ -31,19 +31,36 @@ fn macro_syntax_tree_stats(db: &RootDatabase) -> SyntaxTreeStats {
 //
 // | VS Code | **Rust Analyzer: Status**
 // |===
-pub(crate) fn status(db: &RootDatabase) -> String {
-    let files_stats = FileTextQuery.in_db(db).entries::<FilesStats>();
-    let syntax_tree_stats = syntax_tree_stats(db);
-    let macro_syntax_tree_stats = macro_syntax_tree_stats(db);
-    let symbols_stats = LibrarySymbolsQuery.in_db(db).entries::<LibrarySymbolsStats>();
-    format!(
-        "{}\n{}\n{}\n{} (macros)\n{} total\n",
-        files_stats,
-        symbols_stats,
-        syntax_tree_stats,
-        macro_syntax_tree_stats,
-        memory_usage(),
-    )
+pub(crate) fn status(db: &RootDatabase, file_id: Option<FileId>) -> String {
+    let mut buf = String::new();
+    format_to!(buf, "{}\n", FileTextQuery.in_db(db).entries::<FilesStats>());
+    format_to!(buf, "{}\n", LibrarySymbolsQuery.in_db(db).entries::<LibrarySymbolsStats>());
+    format_to!(buf, "{}\n", syntax_tree_stats(db));
+    format_to!(buf, "{} (macros)\n", macro_syntax_tree_stats(db));
+    format_to!(buf, "{} total\n", memory_usage());
+
+    if let Some(file_id) = file_id {
+        format_to!(buf, "\nfile info:\n");
+        let krate = crate::parent_module::crate_for(db, file_id).pop();
+        match krate {
+            Some(krate) => {
+                let crate_graph = db.crate_graph();
+                let display_crate = |krate: CrateId| match &crate_graph[krate].display_name {
+                    Some(it) => format!("{}({:?})", it, krate),
+                    None => format!("{:?}", krate),
+                };
+                format_to!(buf, "crate: {}\n", display_crate(krate));
+                let deps = crate_graph[krate]
+                    .dependencies
+                    .iter()
+                    .map(|dep| format!("{}={:?}", dep.name, dep.crate_id))
+                    .format(", ");
+                format_to!(buf, "deps: {}\n", deps);
+            }
+            None => format_to!(buf, "does not belong to any crate"),
+        }
+    }
+    buf
 }
 
 #[derive(Default)]
diff --git a/crates/rust-analyzer/src/handlers.rs b/crates/rust-analyzer/src/handlers.rs
index 7ac1a30f6cc..afcec63ad16 100644
--- a/crates/rust-analyzer/src/handlers.rs
+++ b/crates/rust-analyzer/src/handlers.rs
@@ -38,10 +38,22 @@ use crate::{
     to_proto, LspError, Result,
 };
 
-pub(crate) fn handle_analyzer_status(snap: GlobalStateSnapshot, _: ()) -> Result<String> {
+pub(crate) fn handle_analyzer_status(
+    snap: GlobalStateSnapshot,
+    params: lsp_ext::AnalyzerStatusParams,
+) -> Result<String> {
     let _p = profile::span("handle_analyzer_status");
 
     let mut buf = String::new();
+
+    let mut file_id = None;
+    if let Some(tdi) = params.text_document {
+        match from_proto::file_id(&snap, &tdi.uri) {
+            Ok(it) => file_id = Some(it),
+            Err(_) => format_to!(buf, "file {} not found in vfs", tdi.uri),
+        }
+    }
+
     if snap.workspaces.is_empty() {
         buf.push_str("no workspaces\n")
     } else {
@@ -52,7 +64,10 @@ pub(crate) fn handle_analyzer_status(snap: GlobalStateSnapshot, _: ()) -> Result
     }
     buf.push_str("\nanalysis:\n");
     buf.push_str(
-        &snap.analysis.status().unwrap_or_else(|_| "Analysis retrieval was cancelled".to_owned()),
+        &snap
+            .analysis
+            .status(file_id)
+            .unwrap_or_else(|_| "Analysis retrieval was cancelled".to_owned()),
     );
     format_to!(buf, "\n\nrequests:\n");
     let requests = snap.latest_requests.read();
diff --git a/crates/rust-analyzer/src/lsp_ext.rs b/crates/rust-analyzer/src/lsp_ext.rs
index e1a28b1b4ba..43ff191dab5 100644
--- a/crates/rust-analyzer/src/lsp_ext.rs
+++ b/crates/rust-analyzer/src/lsp_ext.rs
@@ -11,11 +11,17 @@ use serde::{Deserialize, Serialize};
 pub enum AnalyzerStatus {}
 
 impl Request for AnalyzerStatus {
-    type Params = ();
+    type Params = AnalyzerStatusParams;
     type Result = String;
     const METHOD: &'static str = "rust-analyzer/analyzerStatus";
 }
 
+#[derive(Deserialize, Serialize, Debug)]
+#[serde(rename_all = "camelCase")]
+pub struct AnalyzerStatusParams {
+    pub text_document: Option<TextDocumentIdentifier>,
+}
+
 pub enum MemoryUsage {}
 
 impl Request for MemoryUsage {
diff --git a/docs/dev/lsp-extensions.md b/docs/dev/lsp-extensions.md
index 2e3133449fb..f1160bb1cc9 100644
--- a/docs/dev/lsp-extensions.md
+++ b/docs/dev/lsp-extensions.md
@@ -390,7 +390,14 @@ rust-analyzer supports only one `kind`, `"cargo"`. The `args` for `"cargo"` look
 
 **Method:** `rust-analyzer/analyzerStatus`
 
-**Request:** `null`
+**Request:**
+
+```typescript
+interface AnalyzerStatusParams {
+    /// If specified, show dependencies of the current file.
+    textDocument?: TextDocumentIdentifier;
+}
+```
 
 **Response:** `string`
 
diff --git a/docs/user/manual.adoc b/docs/user/manual.adoc
index 7d85b36cb31..c1a7788520c 100644
--- a/docs/user/manual.adoc
+++ b/docs/user/manual.adoc
@@ -113,8 +113,8 @@ Note that installing via `xtask install` does not work for VS Code Remote, inste
 
 Here are some useful self-diagnostic commands:
 
-* **Rust Analyzer: Show RA Version** shows the version of `rust-analyzer` binary
-* **Rust Analyzer: Status** prints some statistics about the server, like the few latest LSP requests
+* **Rust Analyzer: Show RA Version** shows the version of `rust-analyzer` binary.
+* **Rust Analyzer: Status** prints some statistics about the server, and dependency information for the current file.
 * To enable server-side logging, run with `env RA_LOG=info` and see `Output > Rust Analyzer Language Server` in VS Code's panel.
 * To log all LSP requests, add `"rust-analyzer.trace.server": "verbose"` to the settings and look for `Rust Analyzer Language Server Trace` in the panel.
 * To enable client-side logging, add `"rust-analyzer.trace.extension": true` to the settings and open `Output > Rust Analyzer Client` in the panel.
diff --git a/editors/code/src/commands.ts b/editors/code/src/commands.ts
index e9581a9b591..1a90f1b7d9a 100644
--- a/editors/code/src/commands.ts
+++ b/editors/code/src/commands.ts
@@ -21,7 +21,12 @@ export function analyzerStatus(ctx: Ctx): Cmd {
         provideTextDocumentContent(_uri: vscode.Uri): vscode.ProviderResult<string> {
             if (!vscode.window.activeTextEditor) return '';
 
-            return ctx.client.sendRequest(ra.analyzerStatus);
+            const params: ra.AnalyzerStatusParams = {};
+            const doc = ctx.activeRustEditor?.document;
+            if (doc != null) {
+                params.textDocument = ctx.client.code2ProtocolConverter.asTextDocumentIdentifier(doc);
+            }
+            return ctx.client.sendRequest(ra.analyzerStatus, params);
         }
 
         get onDidChange(): vscode.Event<vscode.Uri> {
@@ -94,7 +99,7 @@ export function matchingBrace(ctx: Ctx): Cmd {
         if (!editor || !client) return;
 
         const response = await client.sendRequest(ra.matchingBrace, {
-            textDocument: { uri: editor.document.uri.toString() },
+            textDocument: ctx.client.code2ProtocolConverter.asTextDocumentIdentifier(editor.document),
             positions: editor.selections.map(s =>
                 client.code2ProtocolConverter.asPosition(s.active),
             ),
@@ -118,7 +123,7 @@ export function joinLines(ctx: Ctx): Cmd {
 
         const items: lc.TextEdit[] = await client.sendRequest(ra.joinLines, {
             ranges: editor.selections.map((it) => client.code2ProtocolConverter.asRange(it)),
-            textDocument: { uri: editor.document.uri.toString() },
+            textDocument: ctx.client.code2ProtocolConverter.asTextDocumentIdentifier(editor.document),
         });
         editor.edit((builder) => {
             client.protocol2CodeConverter.asTextEdits(items).forEach((edit: any) => {
@@ -136,7 +141,7 @@ export function onEnter(ctx: Ctx): Cmd {
         if (!editor || !client) return false;
 
         const lcEdits = await client.sendRequest(ra.onEnter, {
-            textDocument: { uri: editor.document.uri.toString() },
+            textDocument: ctx.client.code2ProtocolConverter.asTextDocumentIdentifier(editor.document),
             position: client.code2ProtocolConverter.asPosition(
                 editor.selection.active,
             ),
@@ -165,7 +170,7 @@ export function parentModule(ctx: Ctx): Cmd {
         if (!editor || !client) return;
 
         const response = await client.sendRequest(ra.parentModule, {
-            textDocument: { uri: editor.document.uri.toString() },
+            textDocument: ctx.client.code2ProtocolConverter.asTextDocumentIdentifier(editor.document),
             position: client.code2ProtocolConverter.asPosition(
                 editor.selection.active,
             ),
@@ -191,7 +196,7 @@ export function ssr(ctx: Ctx): Cmd {
 
         const position = editor.selection.active;
         const selections = editor.selections;
-        const textDocument = { uri: editor.document.uri.toString() };
+        const textDocument = ctx.client.code2ProtocolConverter.asTextDocumentIdentifier(editor.document);
 
         const options: vscode.InputBoxOptions = {
             value: "() ==>> ()",
@@ -339,7 +344,7 @@ export function expandMacro(ctx: Ctx): Cmd {
             const position = editor.selection.active;
 
             const expanded = await client.sendRequest(ra.expandMacro, {
-                textDocument: { uri: editor.document.uri.toString() },
+                textDocument: ctx.client.code2ProtocolConverter.asTextDocumentIdentifier(editor.document),
                 position,
             });
 
diff --git a/editors/code/src/lsp_ext.ts b/editors/code/src/lsp_ext.ts
index d167041c4c2..eb422d3e759 100644
--- a/editors/code/src/lsp_ext.ts
+++ b/editors/code/src/lsp_ext.ts
@@ -4,7 +4,10 @@
 
 import * as lc from "vscode-languageclient";
 
-export const analyzerStatus = new lc.RequestType0<string, void>("rust-analyzer/analyzerStatus");
+export interface AnalyzerStatusParams {
+    textDocument?: lc.TextDocumentIdentifier;
+}
+export const analyzerStatus = new lc.RequestType<AnalyzerStatusParams, string, void>("rust-analyzer/analyzerStatus");
 export const memoryUsage = new lc.RequestType0<string, void>("rust-analyzer/memoryUsage");
 
 export type Status = "loading" | "ready" | "invalid" | "needsReload";