diff options
-rw-r--r-- | crates/hir/src/code_model.rs | 15 | ||||
-rw-r--r-- | crates/ide/src/lib.rs | 5 | ||||
-rw-r--r-- | crates/ide/src/view_hir.rs | 25 | ||||
-rw-r--r-- | crates/rust-analyzer/src/handlers.rs | 10 | ||||
-rw-r--r-- | crates/rust-analyzer/src/lsp_ext.rs | 8 | ||||
-rw-r--r-- | crates/rust-analyzer/src/main_loop.rs | 1 | ||||
-rw-r--r-- | docs/dev/README.md | 2 | ||||
-rw-r--r-- | docs/dev/lsp-extensions.md | 13 | ||||
-rw-r--r-- | editors/code/package.json | 9 | ||||
-rw-r--r-- | editors/code/src/commands.ts | 55 | ||||
-rw-r--r-- | editors/code/src/lsp_ext.ts | 1 | ||||
-rw-r--r-- | editors/code/src/main.ts | 1 |
12 files changed, 143 insertions, 2 deletions
diff --git a/crates/hir/src/code_model.rs b/crates/hir/src/code_model.rs index 3c83231cf..62eccf475 100644 --- a/crates/hir/src/code_model.rs +++ b/crates/hir/src/code_model.rs | |||
@@ -39,7 +39,7 @@ use hir_ty::{ | |||
39 | TyDefId, TyKind, TypeCtor, | 39 | TyDefId, TyKind, TypeCtor, |
40 | }; | 40 | }; |
41 | use rustc_hash::FxHashSet; | 41 | use rustc_hash::FxHashSet; |
42 | use stdx::impl_from; | 42 | use stdx::{format_to, impl_from}; |
43 | use syntax::{ | 43 | use syntax::{ |
44 | ast::{self, AttrsOwner, NameOwner}, | 44 | ast::{self, AttrsOwner, NameOwner}, |
45 | AstNode, SmolStr, | 45 | AstNode, SmolStr, |
@@ -797,6 +797,19 @@ impl Function { | |||
797 | pub fn has_body(self, db: &dyn HirDatabase) -> bool { | 797 | pub fn has_body(self, db: &dyn HirDatabase) -> bool { |
798 | db.function_data(self.id).has_body | 798 | db.function_data(self.id).has_body |
799 | } | 799 | } |
800 | |||
801 | /// A textual representation of the HIR of this function for debugging purposes. | ||
802 | pub fn debug_hir(self, db: &dyn HirDatabase) -> String { | ||
803 | let body = db.body(self.id.into()); | ||
804 | |||
805 | let mut result = String::new(); | ||
806 | format_to!(result, "HIR expressions in the body of `{}`:\n", self.name(db)); | ||
807 | for (id, expr) in body.exprs.iter() { | ||
808 | format_to!(result, "{:?}: {:?}\n", id, expr); | ||
809 | } | ||
810 | |||
811 | result | ||
812 | } | ||
800 | } | 813 | } |
801 | 814 | ||
802 | // Note: logically, this belongs to `hir_ty`, but we are not using it there yet. | 815 | // Note: logically, this belongs to `hir_ty`, but we are not using it there yet. |
diff --git a/crates/ide/src/lib.rs b/crates/ide/src/lib.rs index b3331f03f..a450794f3 100644 --- a/crates/ide/src/lib.rs +++ b/crates/ide/src/lib.rs | |||
@@ -31,6 +31,7 @@ mod folding_ranges; | |||
31 | mod goto_definition; | 31 | mod goto_definition; |
32 | mod goto_implementation; | 32 | mod goto_implementation; |
33 | mod goto_type_definition; | 33 | mod goto_type_definition; |
34 | mod view_hir; | ||
34 | mod hover; | 35 | mod hover; |
35 | mod inlay_hints; | 36 | mod inlay_hints; |
36 | mod join_lines; | 37 | mod join_lines; |
@@ -271,6 +272,10 @@ impl Analysis { | |||
271 | self.with_db(|db| syntax_tree::syntax_tree(&db, file_id, text_range)) | 272 | self.with_db(|db| syntax_tree::syntax_tree(&db, file_id, text_range)) |
272 | } | 273 | } |
273 | 274 | ||
275 | pub fn view_hir(&self, position: FilePosition) -> Cancelable<String> { | ||
276 | self.with_db(|db| view_hir::view_hir(&db, position)) | ||
277 | } | ||
278 | |||
274 | pub fn expand_macro(&self, position: FilePosition) -> Cancelable<Option<ExpandedMacro>> { | 279 | pub fn expand_macro(&self, position: FilePosition) -> Cancelable<Option<ExpandedMacro>> { |
275 | self.with_db(|db| expand_macro::expand_macro(db, position)) | 280 | self.with_db(|db| expand_macro::expand_macro(db, position)) |
276 | } | 281 | } |
diff --git a/crates/ide/src/view_hir.rs b/crates/ide/src/view_hir.rs new file mode 100644 index 000000000..cfcfb7cfb --- /dev/null +++ b/crates/ide/src/view_hir.rs | |||
@@ -0,0 +1,25 @@ | |||
1 | use hir::{Function, Semantics}; | ||
2 | use ide_db::base_db::FilePosition; | ||
3 | use ide_db::RootDatabase; | ||
4 | use syntax::{algo::find_node_at_offset, ast, AstNode}; | ||
5 | |||
6 | // Feature: View Hir | ||
7 | // | ||
8 | // |=== | ||
9 | // | Editor | Action Name | ||
10 | // | ||
11 | // | VS Code | **Rust Analyzer: View Hir** | ||
12 | // |=== | ||
13 | pub(crate) fn view_hir(db: &RootDatabase, position: FilePosition) -> String { | ||
14 | body_hir(db, position).unwrap_or("Not inside a function body".to_string()) | ||
15 | } | ||
16 | |||
17 | fn body_hir(db: &RootDatabase, position: FilePosition) -> Option<String> { | ||
18 | let sema = Semantics::new(db); | ||
19 | let source_file = sema.parse(position.file_id); | ||
20 | |||
21 | let function = find_node_at_offset::<ast::Fn>(source_file.syntax(), position.offset)?; | ||
22 | |||
23 | let function: Function = sema.to_def(&function)?; | ||
24 | Some(function.debug_hir(db)) | ||
25 | } | ||
diff --git a/crates/rust-analyzer/src/handlers.rs b/crates/rust-analyzer/src/handlers.rs index 948cfc17c..dd486070b 100644 --- a/crates/rust-analyzer/src/handlers.rs +++ b/crates/rust-analyzer/src/handlers.rs | |||
@@ -105,6 +105,16 @@ pub(crate) fn handle_syntax_tree( | |||
105 | Ok(res) | 105 | Ok(res) |
106 | } | 106 | } |
107 | 107 | ||
108 | pub(crate) fn handle_view_hir( | ||
109 | snap: GlobalStateSnapshot, | ||
110 | params: lsp_types::TextDocumentPositionParams, | ||
111 | ) -> Result<String> { | ||
112 | let _p = profile::span("handle_view_hir"); | ||
113 | let position = from_proto::file_position(&snap, params)?; | ||
114 | let res = snap.analysis.view_hir(position)?; | ||
115 | Ok(res) | ||
116 | } | ||
117 | |||
108 | pub(crate) fn handle_expand_macro( | 118 | pub(crate) fn handle_expand_macro( |
109 | snap: GlobalStateSnapshot, | 119 | snap: GlobalStateSnapshot, |
110 | params: lsp_ext::ExpandMacroParams, | 120 | params: lsp_ext::ExpandMacroParams, |
diff --git a/crates/rust-analyzer/src/lsp_ext.rs b/crates/rust-analyzer/src/lsp_ext.rs index 93ac45415..a85978737 100644 --- a/crates/rust-analyzer/src/lsp_ext.rs +++ b/crates/rust-analyzer/src/lsp_ext.rs | |||
@@ -53,6 +53,14 @@ pub struct SyntaxTreeParams { | |||
53 | pub range: Option<Range>, | 53 | pub range: Option<Range>, |
54 | } | 54 | } |
55 | 55 | ||
56 | pub enum ViewHir {} | ||
57 | |||
58 | impl Request for ViewHir { | ||
59 | type Params = lsp_types::TextDocumentPositionParams; | ||
60 | type Result = String; | ||
61 | const METHOD: &'static str = "rust-analyzer/viewHir"; | ||
62 | } | ||
63 | |||
56 | pub enum ExpandMacro {} | 64 | pub enum ExpandMacro {} |
57 | 65 | ||
58 | impl Request for ExpandMacro { | 66 | impl Request for ExpandMacro { |
diff --git a/crates/rust-analyzer/src/main_loop.rs b/crates/rust-analyzer/src/main_loop.rs index 5d55dc96e..8eca79f7e 100644 --- a/crates/rust-analyzer/src/main_loop.rs +++ b/crates/rust-analyzer/src/main_loop.rs | |||
@@ -443,6 +443,7 @@ impl GlobalState { | |||
443 | .on_sync::<lsp_ext::MemoryUsage>(|s, p| handlers::handle_memory_usage(s, p))? | 443 | .on_sync::<lsp_ext::MemoryUsage>(|s, p| handlers::handle_memory_usage(s, p))? |
444 | .on::<lsp_ext::AnalyzerStatus>(handlers::handle_analyzer_status) | 444 | .on::<lsp_ext::AnalyzerStatus>(handlers::handle_analyzer_status) |
445 | .on::<lsp_ext::SyntaxTree>(handlers::handle_syntax_tree) | 445 | .on::<lsp_ext::SyntaxTree>(handlers::handle_syntax_tree) |
446 | .on::<lsp_ext::ViewHir>(handlers::handle_view_hir) | ||
446 | .on::<lsp_ext::ExpandMacro>(handlers::handle_expand_macro) | 447 | .on::<lsp_ext::ExpandMacro>(handlers::handle_expand_macro) |
447 | .on::<lsp_ext::ParentModule>(handlers::handle_parent_module) | 448 | .on::<lsp_ext::ParentModule>(handlers::handle_parent_module) |
448 | .on::<lsp_ext::Runnables>(handlers::handle_runnables) | 449 | .on::<lsp_ext::Runnables>(handlers::handle_runnables) |
diff --git a/docs/dev/README.md b/docs/dev/README.md index 4a2f9feb3..55527bab0 100644 --- a/docs/dev/README.md +++ b/docs/dev/README.md | |||
@@ -227,6 +227,8 @@ There are also two VS Code commands which might be of interest: | |||
227 | 227 | ||
228 | * `Rust Analyzer: Syntax Tree` shows syntax tree of the current file/selection. | 228 | * `Rust Analyzer: Syntax Tree` shows syntax tree of the current file/selection. |
229 | 229 | ||
230 | * `Rust Analyzer: View Hir` shows the HIR expressions within the function containing the cursor. | ||
231 | |||
230 | You can hover over syntax nodes in the opened text file to see the appropriate | 232 | You can hover over syntax nodes in the opened text file to see the appropriate |
231 | rust code that it refers to and the rust editor will also highlight the proper | 233 | rust code that it refers to and the rust editor will also highlight the proper |
232 | text range. | 234 | text range. |
diff --git a/docs/dev/lsp-extensions.md b/docs/dev/lsp-extensions.md index 8c01db07c..78d86f060 100644 --- a/docs/dev/lsp-extensions.md +++ b/docs/dev/lsp-extensions.md | |||
@@ -1,5 +1,5 @@ | |||
1 | <!--- | 1 | <!--- |
2 | lsp_ext.rs hash: 203fdf79b21b5987 | 2 | lsp_ext.rs hash: 91f2c62457e0a20f |
3 | 3 | ||
4 | If you need to change the above hash to make the test pass, please check if you | 4 | If you need to change the above hash to make the test pass, please check if you |
5 | need to adjust this doc as well and ping this issue: | 5 | need to adjust this doc as well and ping this issue: |
@@ -449,6 +449,17 @@ interface SyntaxTeeParams { | |||
449 | Returns textual representation of a parse tree for the file/selected region. | 449 | Returns textual representation of a parse tree for the file/selected region. |
450 | Primarily for debugging, but very useful for all people working on rust-analyzer itself. | 450 | Primarily for debugging, but very useful for all people working on rust-analyzer itself. |
451 | 451 | ||
452 | ## View Hir | ||
453 | |||
454 | **Method:** `rust-analyzer/viewHir` | ||
455 | |||
456 | **Request:** `TextDocumentPositionParams` | ||
457 | |||
458 | **Response:** `string` | ||
459 | |||
460 | Returns a textual representation of the HIR of the function containing the cursor. | ||
461 | For debugging or when working on rust-analyzer itself. | ||
462 | |||
452 | ## Expand Macro | 463 | ## Expand Macro |
453 | 464 | ||
454 | **Method:** `rust-analyzer/expandMacro` | 465 | **Method:** `rust-analyzer/expandMacro` |
diff --git a/editors/code/package.json b/editors/code/package.json index 587f11b90..3e55a3523 100644 --- a/editors/code/package.json +++ b/editors/code/package.json | |||
@@ -104,6 +104,11 @@ | |||
104 | "category": "Rust Analyzer" | 104 | "category": "Rust Analyzer" |
105 | }, | 105 | }, |
106 | { | 106 | { |
107 | "command": "rust-analyzer.viewHir", | ||
108 | "title": "View Hir", | ||
109 | "category": "Rust Analyzer" | ||
110 | }, | ||
111 | { | ||
107 | "command": "rust-analyzer.expandMacro", | 112 | "command": "rust-analyzer.expandMacro", |
108 | "title": "Expand macro recursively", | 113 | "title": "Expand macro recursively", |
109 | "category": "Rust Analyzer" | 114 | "category": "Rust Analyzer" |
@@ -1007,6 +1012,10 @@ | |||
1007 | "when": "inRustProject" | 1012 | "when": "inRustProject" |
1008 | }, | 1013 | }, |
1009 | { | 1014 | { |
1015 | "command": "rust-analyzer.viewHir", | ||
1016 | "when": "inRustProject" | ||
1017 | }, | ||
1018 | { | ||
1010 | "command": "rust-analyzer.expandMacro", | 1019 | "command": "rust-analyzer.expandMacro", |
1011 | "when": "inRustProject" | 1020 | "when": "inRustProject" |
1012 | }, | 1021 | }, |
diff --git a/editors/code/src/commands.ts b/editors/code/src/commands.ts index b12e134ca..c1c9f9754 100644 --- a/editors/code/src/commands.ts +++ b/editors/code/src/commands.ts | |||
@@ -340,6 +340,61 @@ export function syntaxTree(ctx: Ctx): Cmd { | |||
340 | }; | 340 | }; |
341 | } | 341 | } |
342 | 342 | ||
343 | // Opens the virtual file that will show the HIR of the function containing the cursor position | ||
344 | // | ||
345 | // The contents of the file come from the `TextDocumentContentProvider` | ||
346 | export function viewHir(ctx: Ctx): Cmd { | ||
347 | const tdcp = new class implements vscode.TextDocumentContentProvider { | ||
348 | readonly uri = vscode.Uri.parse('rust-analyzer://viewHir/hir.txt'); | ||
349 | readonly eventEmitter = new vscode.EventEmitter<vscode.Uri>(); | ||
350 | constructor() { | ||
351 | vscode.workspace.onDidChangeTextDocument(this.onDidChangeTextDocument, this, ctx.subscriptions); | ||
352 | vscode.window.onDidChangeActiveTextEditor(this.onDidChangeActiveTextEditor, this, ctx.subscriptions); | ||
353 | } | ||
354 | |||
355 | private onDidChangeTextDocument(event: vscode.TextDocumentChangeEvent) { | ||
356 | if (isRustDocument(event.document)) { | ||
357 | // We need to order this after language server updates, but there's no API for that. | ||
358 | // Hence, good old sleep(). | ||
359 | void sleep(10).then(() => this.eventEmitter.fire(this.uri)); | ||
360 | } | ||
361 | } | ||
362 | private onDidChangeActiveTextEditor(editor: vscode.TextEditor | undefined) { | ||
363 | if (editor && isRustEditor(editor)) { | ||
364 | this.eventEmitter.fire(this.uri); | ||
365 | } | ||
366 | } | ||
367 | |||
368 | provideTextDocumentContent(_uri: vscode.Uri, ct: vscode.CancellationToken): vscode.ProviderResult<string> { | ||
369 | const rustEditor = ctx.activeRustEditor; | ||
370 | const client = ctx.client; | ||
371 | if (!rustEditor || !client) return ''; | ||
372 | |||
373 | const params = { | ||
374 | textDocument: client.code2ProtocolConverter.asTextDocumentIdentifier(rustEditor.document), | ||
375 | position: client.code2ProtocolConverter.asPosition( | ||
376 | rustEditor.selection.active, | ||
377 | ), | ||
378 | }; | ||
379 | return client.sendRequest(ra.viewHir, params, ct); | ||
380 | } | ||
381 | |||
382 | get onDidChange(): vscode.Event<vscode.Uri> { | ||
383 | return this.eventEmitter.event; | ||
384 | } | ||
385 | }; | ||
386 | |||
387 | ctx.pushCleanup(vscode.workspace.registerTextDocumentContentProvider('rust-analyzer', tdcp)); | ||
388 | |||
389 | return async () => { | ||
390 | const document = await vscode.workspace.openTextDocument(tdcp.uri); | ||
391 | tdcp.eventEmitter.fire(tdcp.uri); | ||
392 | void await vscode.window.showTextDocument(document, { | ||
393 | viewColumn: vscode.ViewColumn.Two, | ||
394 | preserveFocus: true | ||
395 | }); | ||
396 | }; | ||
397 | } | ||
343 | 398 | ||
344 | // Opens the virtual file that will show the syntax tree | 399 | // Opens the virtual file that will show the syntax tree |
345 | // | 400 | // |
diff --git a/editors/code/src/lsp_ext.ts b/editors/code/src/lsp_ext.ts index 5e877ce65..d21a3db86 100644 --- a/editors/code/src/lsp_ext.ts +++ b/editors/code/src/lsp_ext.ts | |||
@@ -24,6 +24,7 @@ export interface SyntaxTreeParams { | |||
24 | } | 24 | } |
25 | export const syntaxTree = new lc.RequestType<SyntaxTreeParams, string, void>("rust-analyzer/syntaxTree"); | 25 | export const syntaxTree = new lc.RequestType<SyntaxTreeParams, string, void>("rust-analyzer/syntaxTree"); |
26 | 26 | ||
27 | export const viewHir = new lc.RequestType<lc.TextDocumentPositionParams, string, void>("rust-analyzer/viewHir"); | ||
27 | 28 | ||
28 | export interface ExpandMacroParams { | 29 | export interface ExpandMacroParams { |
29 | textDocument: lc.TextDocumentIdentifier; | 30 | textDocument: lc.TextDocumentIdentifier; |
diff --git a/editors/code/src/main.ts b/editors/code/src/main.ts index 282240d84..60907dfd4 100644 --- a/editors/code/src/main.ts +++ b/editors/code/src/main.ts | |||
@@ -105,6 +105,7 @@ async function tryActivate(context: vscode.ExtensionContext) { | |||
105 | ctx.registerCommand('joinLines', commands.joinLines); | 105 | ctx.registerCommand('joinLines', commands.joinLines); |
106 | ctx.registerCommand('parentModule', commands.parentModule); | 106 | ctx.registerCommand('parentModule', commands.parentModule); |
107 | ctx.registerCommand('syntaxTree', commands.syntaxTree); | 107 | ctx.registerCommand('syntaxTree', commands.syntaxTree); |
108 | ctx.registerCommand('viewHir', commands.viewHir); | ||
108 | ctx.registerCommand('expandMacro', commands.expandMacro); | 109 | ctx.registerCommand('expandMacro', commands.expandMacro); |
109 | ctx.registerCommand('run', commands.run); | 110 | ctx.registerCommand('run', commands.run); |
110 | ctx.registerCommand('debug', commands.debug); | 111 | ctx.registerCommand('debug', commands.debug); |