aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhil Ellison <[email protected]>2020-12-28 18:29:58 +0000
committerPhil Ellison <[email protected]>2020-12-28 18:29:58 +0000
commit077592a12fd982de3e69572a4c738dd4468617f9 (patch)
tree24bc738d02fb8c88ef662f85e4a0c9a4c8ab0fac
parent1d530756ed7ba175ec32ff71247072798dc9a748 (diff)
Initial implementation of view-hir command
-rw-r--r--crates/hir/src/code_model.rs3
-rw-r--r--crates/ide/src/lib.rs5
-rw-r--r--crates/ide/src/view_hir.rs39
-rw-r--r--crates/rust-analyzer/src/handlers.rs10
-rw-r--r--crates/rust-analyzer/src/lsp_ext.rs8
-rw-r--r--crates/rust-analyzer/src/main_loop.rs1
-rw-r--r--editors/code/package.json9
-rw-r--r--editors/code/src/commands.ts69
-rw-r--r--editors/code/src/lsp_ext.ts1
-rw-r--r--editors/code/src/main.ts1
10 files changed, 145 insertions, 1 deletions
diff --git a/crates/hir/src/code_model.rs b/crates/hir/src/code_model.rs
index b7ded3478..9b78944c6 100644
--- a/crates/hir/src/code_model.rs
+++ b/crates/hir/src/code_model.rs
@@ -729,7 +729,8 @@ impl DefWithBody {
729 729
730#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 730#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
731pub struct Function { 731pub struct Function {
732 pub(crate) id: FunctionId, 732 // DO NOT MERGE: this was previously pub(crate)
733 pub id: FunctionId,
733} 734}
734 735
735impl Function { 736impl Function {
diff --git a/crates/ide/src/lib.rs b/crates/ide/src/lib.rs
index 41eb139d1..25c2047ca 100644
--- a/crates/ide/src/lib.rs
+++ b/crates/ide/src/lib.rs
@@ -31,6 +31,7 @@ mod folding_ranges;
31mod goto_definition; 31mod goto_definition;
32mod goto_implementation; 32mod goto_implementation;
33mod goto_type_definition; 33mod goto_type_definition;
34mod view_hir;
34mod hover; 35mod hover;
35mod inlay_hints; 36mod inlay_hints;
36mod join_lines; 37mod 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..e48f2cfe0
--- /dev/null
+++ b/crates/ide/src/view_hir.rs
@@ -0,0 +1,39 @@
1use hir::{Function, Semantics};
2use hir::db::DefDatabase;
3use ide_db::base_db::FilePosition;
4use ide_db::RootDatabase;
5use syntax::{AstNode, algo::find_node_at_offset, ast};
6use std::fmt::Write;
7
8// Feature: View hir
9//
10// |===
11// | Editor | Action Name
12//
13// | VS Code | **Rust Analyzer: View Hir**
14// |===
15pub(crate) fn view_hir(db: &RootDatabase, position: FilePosition) -> String {
16 body_hir(db, position).unwrap_or("Not inside a function body".to_string())
17}
18
19fn body_hir(db: &RootDatabase, position: FilePosition) -> Option<String> {
20 let sema = Semantics::new(db);
21 let source_file = sema.parse(position.file_id);
22
23 let function = find_node_at_offset::<ast::Fn>(
24 source_file.syntax(),
25 position.offset,
26 )?;
27
28 let function: Function = sema.to_def(&function)?;
29 let body = db.body(function.id.into());
30
31 let mut result = String::new();
32 writeln!(&mut result, "== Body expressions ==").ok()?;
33
34 for (id, expr) in body.exprs.iter() {
35 writeln!(&mut result, "{:?}: {:?}", id, expr).ok()?;
36 }
37
38 Some(result)
39} \ No newline at end of file
diff --git a/crates/rust-analyzer/src/handlers.rs b/crates/rust-analyzer/src/handlers.rs
index 374fb5302..85f1f81ad 100644
--- a/crates/rust-analyzer/src/handlers.rs
+++ b/crates/rust-analyzer/src/handlers.rs
@@ -104,6 +104,16 @@ pub(crate) fn handle_syntax_tree(
104 Ok(res) 104 Ok(res)
105} 105}
106 106
107pub(crate) fn handle_view_hir(
108 snap: GlobalStateSnapshot,
109 params: lsp_types::TextDocumentPositionParams,
110) -> Result<String> {
111 let _p = profile::span("handle_view_hir");
112 let position = from_proto::file_position(&snap, params)?;
113 let res = snap.analysis.view_hir(position)?;
114 Ok(res)
115}
116
107pub(crate) fn handle_expand_macro( 117pub(crate) fn handle_expand_macro(
108 snap: GlobalStateSnapshot, 118 snap: GlobalStateSnapshot,
109 params: lsp_ext::ExpandMacroParams, 119 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
56pub enum ViewHir {}
57
58impl Request for ViewHir {
59 type Params = lsp_types::TextDocumentPositionParams;
60 type Result = String;
61 const METHOD: &'static str = "rust-analyzer/viewHir";
62}
63
56pub enum ExpandMacro {} 64pub enum ExpandMacro {}
57 65
58impl Request for ExpandMacro { 66impl 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/editors/code/package.json b/editors/code/package.json
index 13749a084..4bae5d647 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"
@@ -999,6 +1004,10 @@
999 "when": "inRustProject" 1004 "when": "inRustProject"
1000 }, 1005 },
1001 { 1006 {
1007 "command": "rust-analyzer.viewHir",
1008 "when": "inRustProject"
1009 },
1010 {
1002 "command": "rust-analyzer.expandMacro", 1011 "command": "rust-analyzer.expandMacro",
1003 "when": "inRustProject" 1012 "when": "inRustProject"
1004 }, 1013 },
diff --git a/editors/code/src/commands.ts b/editors/code/src/commands.ts
index 9d4823a34..21b0c27f3 100644
--- a/editors/code/src/commands.ts
+++ b/editors/code/src/commands.ts
@@ -340,6 +340,75 @@ export function syntaxTree(ctx: Ctx): Cmd {
340 }; 340 };
341} 341}
342 342
343// Opens the virtual file that will show hir
344//
345// The contents of the file come from the `TextDocumentContentProvider`
346export 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 void new AstInspector(ctx);
388
389 ctx.pushCleanup(vscode.workspace.registerTextDocumentContentProvider('rust-analyzer', tdcp));
390 ctx.pushCleanup(vscode.languages.setLanguageConfiguration("ra_syntax_tree", {
391 brackets: [["[", ")"]],
392 }));
393
394 return async () => {
395 const editor = vscode.window.activeTextEditor;
396 const rangeEnabled = !!editor && !editor.selection.isEmpty;
397
398 const uri = rangeEnabled
399 ? vscode.Uri.parse(`${tdcp.uri.toString()}?range=true`)
400 : tdcp.uri;
401
402 const document = await vscode.workspace.openTextDocument(uri);
403
404 tdcp.eventEmitter.fire(uri);
405
406 void await vscode.window.showTextDocument(document, {
407 viewColumn: vscode.ViewColumn.Two,
408 preserveFocus: true
409 });
410 };
411}
343 412
344// Opens the virtual file that will show the syntax tree 413// Opens the virtual file that will show the syntax tree
345// 414//
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}
25export const syntaxTree = new lc.RequestType<SyntaxTreeParams, string, void>("rust-analyzer/syntaxTree"); 25export const syntaxTree = new lc.RequestType<SyntaxTreeParams, string, void>("rust-analyzer/syntaxTree");
26 26
27export const viewHir = new lc.RequestType<lc.TextDocumentPositionParams, string, void>("rust-analyzer/viewHir");
27 28
28export interface ExpandMacroParams { 29export 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);