diff options
author | Aleksey Kladov <[email protected]> | 2020-09-29 21:05:18 +0100 |
---|---|---|
committer | Aleksey Kladov <[email protected]> | 2020-09-29 21:13:23 +0100 |
commit | af8063fe373cf06a345b0d4eee14ef1ef6873bc7 (patch) | |
tree | 8d8e459960c98fa9c491f25ef755543363dec76e | |
parent | e7df0ad2fb48166937fdd061e1ae559c72a81990 (diff) |
Extend **Status** command to also show dep info for the file
This should help with troubleshooting wrong project configuration
-rw-r--r-- | crates/ide/src/lib.rs | 4 | ||||
-rw-r--r-- | crates/ide/src/status.rs | 49 | ||||
-rw-r--r-- | crates/rust-analyzer/src/handlers.rs | 19 | ||||
-rw-r--r-- | crates/rust-analyzer/src/lsp_ext.rs | 8 | ||||
-rw-r--r-- | docs/dev/lsp-extensions.md | 9 | ||||
-rw-r--r-- | docs/user/manual.adoc | 4 | ||||
-rw-r--r-- | editors/code/src/commands.ts | 19 | ||||
-rw-r--r-- | editors/code/src/lsp_ext.ts | 5 |
8 files changed, 85 insertions, 32 deletions
diff --git a/crates/ide/src/lib.rs b/crates/ide/src/lib.rs index 96dae9ee0..6d5fd1a55 100644 --- a/crates/ide/src/lib.rs +++ b/crates/ide/src/lib.rs | |||
@@ -216,8 +216,8 @@ impl Analysis { | |||
216 | } | 216 | } |
217 | 217 | ||
218 | /// Debug info about the current state of the analysis. | 218 | /// Debug info about the current state of the analysis. |
219 | pub fn status(&self) -> Cancelable<String> { | 219 | pub fn status(&self, file_id: Option<FileId>) -> Cancelable<String> { |
220 | self.with_db(|db| status::status(&*db)) | 220 | self.with_db(|db| status::status(&*db, file_id)) |
221 | } | 221 | } |
222 | 222 | ||
223 | pub fn prime_caches(&self, files: Vec<FileId>) -> Cancelable<()> { | 223 | pub fn prime_caches(&self, files: Vec<FileId>) -> Cancelable<()> { |
diff --git a/crates/ide/src/status.rs b/crates/ide/src/status.rs index 1427c50cf..0af84daa0 100644 --- a/crates/ide/src/status.rs +++ b/crates/ide/src/status.rs | |||
@@ -2,19 +2,19 @@ use std::{fmt, iter::FromIterator, sync::Arc}; | |||
2 | 2 | ||
3 | use base_db::{ | 3 | use base_db::{ |
4 | salsa::debug::{DebugQueryTable, TableEntry}, | 4 | salsa::debug::{DebugQueryTable, TableEntry}, |
5 | FileTextQuery, SourceRootId, | 5 | CrateId, FileId, FileTextQuery, SourceDatabase, SourceRootId, |
6 | }; | 6 | }; |
7 | use hir::MacroFile; | 7 | use hir::MacroFile; |
8 | use ide_db::{ | 8 | use ide_db::{ |
9 | symbol_index::{LibrarySymbolsQuery, SymbolIndex}, | 9 | symbol_index::{LibrarySymbolsQuery, SymbolIndex}, |
10 | RootDatabase, | 10 | RootDatabase, |
11 | }; | 11 | }; |
12 | use itertools::Itertools; | ||
12 | use profile::{memory_usage, Bytes}; | 13 | use profile::{memory_usage, Bytes}; |
13 | use rustc_hash::FxHashMap; | 14 | use rustc_hash::FxHashMap; |
15 | use stdx::format_to; | ||
14 | use syntax::{ast, Parse, SyntaxNode}; | 16 | use syntax::{ast, Parse, SyntaxNode}; |
15 | 17 | ||
16 | use crate::FileId; | ||
17 | |||
18 | fn syntax_tree_stats(db: &RootDatabase) -> SyntaxTreeStats { | 18 | fn syntax_tree_stats(db: &RootDatabase) -> SyntaxTreeStats { |
19 | base_db::ParseQuery.in_db(db).entries::<SyntaxTreeStats>() | 19 | base_db::ParseQuery.in_db(db).entries::<SyntaxTreeStats>() |
20 | } | 20 | } |
@@ -31,19 +31,36 @@ fn macro_syntax_tree_stats(db: &RootDatabase) -> SyntaxTreeStats { | |||
31 | // | 31 | // |
32 | // | VS Code | **Rust Analyzer: Status** | 32 | // | VS Code | **Rust Analyzer: Status** |
33 | // |=== | 33 | // |=== |
34 | pub(crate) fn status(db: &RootDatabase) -> String { | 34 | pub(crate) fn status(db: &RootDatabase, file_id: Option<FileId>) -> String { |
35 | let files_stats = FileTextQuery.in_db(db).entries::<FilesStats>(); | 35 | let mut buf = String::new(); |
36 | let syntax_tree_stats = syntax_tree_stats(db); | 36 | format_to!(buf, "{}\n", FileTextQuery.in_db(db).entries::<FilesStats>()); |
37 | let macro_syntax_tree_stats = macro_syntax_tree_stats(db); | 37 | format_to!(buf, "{}\n", LibrarySymbolsQuery.in_db(db).entries::<LibrarySymbolsStats>()); |
38 | let symbols_stats = LibrarySymbolsQuery.in_db(db).entries::<LibrarySymbolsStats>(); | 38 | format_to!(buf, "{}\n", syntax_tree_stats(db)); |
39 | format!( | 39 | format_to!(buf, "{} (macros)\n", macro_syntax_tree_stats(db)); |
40 | "{}\n{}\n{}\n{} (macros)\n{} total\n", | 40 | format_to!(buf, "{} total\n", memory_usage()); |
41 | files_stats, | 41 | |
42 | symbols_stats, | 42 | if let Some(file_id) = file_id { |
43 | syntax_tree_stats, | 43 | format_to!(buf, "\nfile info:\n"); |
44 | macro_syntax_tree_stats, | 44 | let krate = crate::parent_module::crate_for(db, file_id).pop(); |
45 | memory_usage(), | 45 | match krate { |
46 | ) | 46 | Some(krate) => { |
47 | let crate_graph = db.crate_graph(); | ||
48 | let display_crate = |krate: CrateId| match &crate_graph[krate].display_name { | ||
49 | Some(it) => format!("{}({:?})", it, krate), | ||
50 | None => format!("{:?}", krate), | ||
51 | }; | ||
52 | format_to!(buf, "crate: {}\n", display_crate(krate)); | ||
53 | let deps = crate_graph[krate] | ||
54 | .dependencies | ||
55 | .iter() | ||
56 | .map(|dep| format!("{}={:?}", dep.name, dep.crate_id)) | ||
57 | .format(", "); | ||
58 | format_to!(buf, "deps: {}\n", deps); | ||
59 | } | ||
60 | None => format_to!(buf, "does not belong to any crate"), | ||
61 | } | ||
62 | } | ||
63 | buf | ||
47 | } | 64 | } |
48 | 65 | ||
49 | #[derive(Default)] | 66 | #[derive(Default)] |
diff --git a/crates/rust-analyzer/src/handlers.rs b/crates/rust-analyzer/src/handlers.rs index 7ac1a30f6..afcec63ad 100644 --- a/crates/rust-analyzer/src/handlers.rs +++ b/crates/rust-analyzer/src/handlers.rs | |||
@@ -38,10 +38,22 @@ use crate::{ | |||
38 | to_proto, LspError, Result, | 38 | to_proto, LspError, Result, |
39 | }; | 39 | }; |
40 | 40 | ||
41 | pub(crate) fn handle_analyzer_status(snap: GlobalStateSnapshot, _: ()) -> Result<String> { | 41 | pub(crate) fn handle_analyzer_status( |
42 | snap: GlobalStateSnapshot, | ||
43 | params: lsp_ext::AnalyzerStatusParams, | ||
44 | ) -> Result<String> { | ||
42 | let _p = profile::span("handle_analyzer_status"); | 45 | let _p = profile::span("handle_analyzer_status"); |
43 | 46 | ||
44 | let mut buf = String::new(); | 47 | let mut buf = String::new(); |
48 | |||
49 | let mut file_id = None; | ||
50 | if let Some(tdi) = params.text_document { | ||
51 | match from_proto::file_id(&snap, &tdi.uri) { | ||
52 | Ok(it) => file_id = Some(it), | ||
53 | Err(_) => format_to!(buf, "file {} not found in vfs", tdi.uri), | ||
54 | } | ||
55 | } | ||
56 | |||
45 | if snap.workspaces.is_empty() { | 57 | if snap.workspaces.is_empty() { |
46 | buf.push_str("no workspaces\n") | 58 | buf.push_str("no workspaces\n") |
47 | } else { | 59 | } else { |
@@ -52,7 +64,10 @@ pub(crate) fn handle_analyzer_status(snap: GlobalStateSnapshot, _: ()) -> Result | |||
52 | } | 64 | } |
53 | buf.push_str("\nanalysis:\n"); | 65 | buf.push_str("\nanalysis:\n"); |
54 | buf.push_str( | 66 | buf.push_str( |
55 | &snap.analysis.status().unwrap_or_else(|_| "Analysis retrieval was cancelled".to_owned()), | 67 | &snap |
68 | .analysis | ||
69 | .status(file_id) | ||
70 | .unwrap_or_else(|_| "Analysis retrieval was cancelled".to_owned()), | ||
56 | ); | 71 | ); |
57 | format_to!(buf, "\n\nrequests:\n"); | 72 | format_to!(buf, "\n\nrequests:\n"); |
58 | let requests = snap.latest_requests.read(); | 73 | 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 e1a28b1b4..43ff191da 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}; | |||
11 | pub enum AnalyzerStatus {} | 11 | pub enum AnalyzerStatus {} |
12 | 12 | ||
13 | impl Request for AnalyzerStatus { | 13 | impl Request for AnalyzerStatus { |
14 | type Params = (); | 14 | type Params = AnalyzerStatusParams; |
15 | type Result = String; | 15 | type Result = String; |
16 | const METHOD: &'static str = "rust-analyzer/analyzerStatus"; | 16 | const METHOD: &'static str = "rust-analyzer/analyzerStatus"; |
17 | } | 17 | } |
18 | 18 | ||
19 | #[derive(Deserialize, Serialize, Debug)] | ||
20 | #[serde(rename_all = "camelCase")] | ||
21 | pub struct AnalyzerStatusParams { | ||
22 | pub text_document: Option<TextDocumentIdentifier>, | ||
23 | } | ||
24 | |||
19 | pub enum MemoryUsage {} | 25 | pub enum MemoryUsage {} |
20 | 26 | ||
21 | impl Request for MemoryUsage { | 27 | impl Request for MemoryUsage { |
diff --git a/docs/dev/lsp-extensions.md b/docs/dev/lsp-extensions.md index 2e3133449..f1160bb1c 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 | |||
390 | 390 | ||
391 | **Method:** `rust-analyzer/analyzerStatus` | 391 | **Method:** `rust-analyzer/analyzerStatus` |
392 | 392 | ||
393 | **Request:** `null` | 393 | **Request:** |
394 | |||
395 | ```typescript | ||
396 | interface AnalyzerStatusParams { | ||
397 | /// If specified, show dependencies of the current file. | ||
398 | textDocument?: TextDocumentIdentifier; | ||
399 | } | ||
400 | ``` | ||
394 | 401 | ||
395 | **Response:** `string` | 402 | **Response:** `string` |
396 | 403 | ||
diff --git a/docs/user/manual.adoc b/docs/user/manual.adoc index 7d85b36cb..c1a778852 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 | |||
113 | 113 | ||
114 | Here are some useful self-diagnostic commands: | 114 | Here are some useful self-diagnostic commands: |
115 | 115 | ||
116 | * **Rust Analyzer: Show RA Version** shows the version of `rust-analyzer` binary | 116 | * **Rust Analyzer: Show RA Version** shows the version of `rust-analyzer` binary. |
117 | * **Rust Analyzer: Status** prints some statistics about the server, like the few latest LSP requests | 117 | * **Rust Analyzer: Status** prints some statistics about the server, and dependency information for the current file. |
118 | * To enable server-side logging, run with `env RA_LOG=info` and see `Output > Rust Analyzer Language Server` in VS Code's panel. | 118 | * To enable server-side logging, run with `env RA_LOG=info` and see `Output > Rust Analyzer Language Server` in VS Code's panel. |
119 | * 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. | 119 | * 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. |
120 | * To enable client-side logging, add `"rust-analyzer.trace.extension": true` to the settings and open `Output > Rust Analyzer Client` in the panel. | 120 | * 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 e9581a9b5..1a90f1b7d 100644 --- a/editors/code/src/commands.ts +++ b/editors/code/src/commands.ts | |||
@@ -21,7 +21,12 @@ export function analyzerStatus(ctx: Ctx): Cmd { | |||
21 | provideTextDocumentContent(_uri: vscode.Uri): vscode.ProviderResult<string> { | 21 | provideTextDocumentContent(_uri: vscode.Uri): vscode.ProviderResult<string> { |
22 | if (!vscode.window.activeTextEditor) return ''; | 22 | if (!vscode.window.activeTextEditor) return ''; |
23 | 23 | ||
24 | return ctx.client.sendRequest(ra.analyzerStatus); | 24 | const params: ra.AnalyzerStatusParams = {}; |
25 | const doc = ctx.activeRustEditor?.document; | ||
26 | if (doc != null) { | ||
27 | params.textDocument = ctx.client.code2ProtocolConverter.asTextDocumentIdentifier(doc); | ||
28 | } | ||
29 | return ctx.client.sendRequest(ra.analyzerStatus, params); | ||
25 | } | 30 | } |
26 | 31 | ||
27 | get onDidChange(): vscode.Event<vscode.Uri> { | 32 | get onDidChange(): vscode.Event<vscode.Uri> { |
@@ -94,7 +99,7 @@ export function matchingBrace(ctx: Ctx): Cmd { | |||
94 | if (!editor || !client) return; | 99 | if (!editor || !client) return; |
95 | 100 | ||
96 | const response = await client.sendRequest(ra.matchingBrace, { | 101 | const response = await client.sendRequest(ra.matchingBrace, { |
97 | textDocument: { uri: editor.document.uri.toString() }, | 102 | textDocument: ctx.client.code2ProtocolConverter.asTextDocumentIdentifier(editor.document), |
98 | positions: editor.selections.map(s => | 103 | positions: editor.selections.map(s => |
99 | client.code2ProtocolConverter.asPosition(s.active), | 104 | client.code2ProtocolConverter.asPosition(s.active), |
100 | ), | 105 | ), |
@@ -118,7 +123,7 @@ export function joinLines(ctx: Ctx): Cmd { | |||
118 | 123 | ||
119 | const items: lc.TextEdit[] = await client.sendRequest(ra.joinLines, { | 124 | const items: lc.TextEdit[] = await client.sendRequest(ra.joinLines, { |
120 | ranges: editor.selections.map((it) => client.code2ProtocolConverter.asRange(it)), | 125 | ranges: editor.selections.map((it) => client.code2ProtocolConverter.asRange(it)), |
121 | textDocument: { uri: editor.document.uri.toString() }, | 126 | textDocument: ctx.client.code2ProtocolConverter.asTextDocumentIdentifier(editor.document), |
122 | }); | 127 | }); |
123 | editor.edit((builder) => { | 128 | editor.edit((builder) => { |
124 | client.protocol2CodeConverter.asTextEdits(items).forEach((edit: any) => { | 129 | client.protocol2CodeConverter.asTextEdits(items).forEach((edit: any) => { |
@@ -136,7 +141,7 @@ export function onEnter(ctx: Ctx): Cmd { | |||
136 | if (!editor || !client) return false; | 141 | if (!editor || !client) return false; |
137 | 142 | ||
138 | const lcEdits = await client.sendRequest(ra.onEnter, { | 143 | const lcEdits = await client.sendRequest(ra.onEnter, { |
139 | textDocument: { uri: editor.document.uri.toString() }, | 144 | textDocument: ctx.client.code2ProtocolConverter.asTextDocumentIdentifier(editor.document), |
140 | position: client.code2ProtocolConverter.asPosition( | 145 | position: client.code2ProtocolConverter.asPosition( |
141 | editor.selection.active, | 146 | editor.selection.active, |
142 | ), | 147 | ), |
@@ -165,7 +170,7 @@ export function parentModule(ctx: Ctx): Cmd { | |||
165 | if (!editor || !client) return; | 170 | if (!editor || !client) return; |
166 | 171 | ||
167 | const response = await client.sendRequest(ra.parentModule, { | 172 | const response = await client.sendRequest(ra.parentModule, { |
168 | textDocument: { uri: editor.document.uri.toString() }, | 173 | textDocument: ctx.client.code2ProtocolConverter.asTextDocumentIdentifier(editor.document), |
169 | position: client.code2ProtocolConverter.asPosition( | 174 | position: client.code2ProtocolConverter.asPosition( |
170 | editor.selection.active, | 175 | editor.selection.active, |
171 | ), | 176 | ), |
@@ -191,7 +196,7 @@ export function ssr(ctx: Ctx): Cmd { | |||
191 | 196 | ||
192 | const position = editor.selection.active; | 197 | const position = editor.selection.active; |
193 | const selections = editor.selections; | 198 | const selections = editor.selections; |
194 | const textDocument = { uri: editor.document.uri.toString() }; | 199 | const textDocument = ctx.client.code2ProtocolConverter.asTextDocumentIdentifier(editor.document); |
195 | 200 | ||
196 | const options: vscode.InputBoxOptions = { | 201 | const options: vscode.InputBoxOptions = { |
197 | value: "() ==>> ()", | 202 | value: "() ==>> ()", |
@@ -339,7 +344,7 @@ export function expandMacro(ctx: Ctx): Cmd { | |||
339 | const position = editor.selection.active; | 344 | const position = editor.selection.active; |
340 | 345 | ||
341 | const expanded = await client.sendRequest(ra.expandMacro, { | 346 | const expanded = await client.sendRequest(ra.expandMacro, { |
342 | textDocument: { uri: editor.document.uri.toString() }, | 347 | textDocument: ctx.client.code2ProtocolConverter.asTextDocumentIdentifier(editor.document), |
343 | position, | 348 | position, |
344 | }); | 349 | }); |
345 | 350 | ||
diff --git a/editors/code/src/lsp_ext.ts b/editors/code/src/lsp_ext.ts index d167041c4..eb422d3e7 100644 --- a/editors/code/src/lsp_ext.ts +++ b/editors/code/src/lsp_ext.ts | |||
@@ -4,7 +4,10 @@ | |||
4 | 4 | ||
5 | import * as lc from "vscode-languageclient"; | 5 | import * as lc from "vscode-languageclient"; |
6 | 6 | ||
7 | export const analyzerStatus = new lc.RequestType0<string, void>("rust-analyzer/analyzerStatus"); | 7 | export interface AnalyzerStatusParams { |
8 | textDocument?: lc.TextDocumentIdentifier; | ||
9 | } | ||
10 | export const analyzerStatus = new lc.RequestType<AnalyzerStatusParams, string, void>("rust-analyzer/analyzerStatus"); | ||
8 | export const memoryUsage = new lc.RequestType0<string, void>("rust-analyzer/memoryUsage"); | 11 | export const memoryUsage = new lc.RequestType0<string, void>("rust-analyzer/memoryUsage"); |
9 | 12 | ||
10 | export type Status = "loading" | "ready" | "invalid" | "needsReload"; | 13 | export type Status = "loading" | "ready" | "invalid" | "needsReload"; |