mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-12-26 04:53:34 +00:00
Initial implementation of view-hir command
This commit is contained in:
parent
1d530756ed
commit
077592a12f
10 changed files with 145 additions and 1 deletions
|
@ -729,7 +729,8 @@ impl DefWithBody {
|
|||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
pub struct Function {
|
||||
pub(crate) id: FunctionId,
|
||||
// DO NOT MERGE: this was previously pub(crate)
|
||||
pub id: FunctionId,
|
||||
}
|
||||
|
||||
impl Function {
|
||||
|
|
|
@ -31,6 +31,7 @@ mod folding_ranges;
|
|||
mod goto_definition;
|
||||
mod goto_implementation;
|
||||
mod goto_type_definition;
|
||||
mod view_hir;
|
||||
mod hover;
|
||||
mod inlay_hints;
|
||||
mod join_lines;
|
||||
|
@ -271,6 +272,10 @@ impl Analysis {
|
|||
self.with_db(|db| syntax_tree::syntax_tree(&db, file_id, text_range))
|
||||
}
|
||||
|
||||
pub fn view_hir(&self, position: FilePosition) -> Cancelable<String> {
|
||||
self.with_db(|db| view_hir::view_hir(&db, position))
|
||||
}
|
||||
|
||||
pub fn expand_macro(&self, position: FilePosition) -> Cancelable<Option<ExpandedMacro>> {
|
||||
self.with_db(|db| expand_macro::expand_macro(db, position))
|
||||
}
|
||||
|
|
39
crates/ide/src/view_hir.rs
Normal file
39
crates/ide/src/view_hir.rs
Normal file
|
@ -0,0 +1,39 @@
|
|||
use hir::{Function, Semantics};
|
||||
use hir::db::DefDatabase;
|
||||
use ide_db::base_db::FilePosition;
|
||||
use ide_db::RootDatabase;
|
||||
use syntax::{AstNode, algo::find_node_at_offset, ast};
|
||||
use std::fmt::Write;
|
||||
|
||||
// Feature: View hir
|
||||
//
|
||||
// |===
|
||||
// | Editor | Action Name
|
||||
//
|
||||
// | VS Code | **Rust Analyzer: View Hir**
|
||||
// |===
|
||||
pub(crate) fn view_hir(db: &RootDatabase, position: FilePosition) -> String {
|
||||
body_hir(db, position).unwrap_or("Not inside a function body".to_string())
|
||||
}
|
||||
|
||||
fn body_hir(db: &RootDatabase, position: FilePosition) -> Option<String> {
|
||||
let sema = Semantics::new(db);
|
||||
let source_file = sema.parse(position.file_id);
|
||||
|
||||
let function = find_node_at_offset::<ast::Fn>(
|
||||
source_file.syntax(),
|
||||
position.offset,
|
||||
)?;
|
||||
|
||||
let function: Function = sema.to_def(&function)?;
|
||||
let body = db.body(function.id.into());
|
||||
|
||||
let mut result = String::new();
|
||||
writeln!(&mut result, "== Body expressions ==").ok()?;
|
||||
|
||||
for (id, expr) in body.exprs.iter() {
|
||||
writeln!(&mut result, "{:?}: {:?}", id, expr).ok()?;
|
||||
}
|
||||
|
||||
Some(result)
|
||||
}
|
|
@ -104,6 +104,16 @@ pub(crate) fn handle_syntax_tree(
|
|||
Ok(res)
|
||||
}
|
||||
|
||||
pub(crate) fn handle_view_hir(
|
||||
snap: GlobalStateSnapshot,
|
||||
params: lsp_types::TextDocumentPositionParams,
|
||||
) -> Result<String> {
|
||||
let _p = profile::span("handle_view_hir");
|
||||
let position = from_proto::file_position(&snap, params)?;
|
||||
let res = snap.analysis.view_hir(position)?;
|
||||
Ok(res)
|
||||
}
|
||||
|
||||
pub(crate) fn handle_expand_macro(
|
||||
snap: GlobalStateSnapshot,
|
||||
params: lsp_ext::ExpandMacroParams,
|
||||
|
|
|
@ -53,6 +53,14 @@ pub struct SyntaxTreeParams {
|
|||
pub range: Option<Range>,
|
||||
}
|
||||
|
||||
pub enum ViewHir {}
|
||||
|
||||
impl Request for ViewHir {
|
||||
type Params = lsp_types::TextDocumentPositionParams;
|
||||
type Result = String;
|
||||
const METHOD: &'static str = "rust-analyzer/viewHir";
|
||||
}
|
||||
|
||||
pub enum ExpandMacro {}
|
||||
|
||||
impl Request for ExpandMacro {
|
||||
|
|
|
@ -443,6 +443,7 @@ impl GlobalState {
|
|||
.on_sync::<lsp_ext::MemoryUsage>(|s, p| handlers::handle_memory_usage(s, p))?
|
||||
.on::<lsp_ext::AnalyzerStatus>(handlers::handle_analyzer_status)
|
||||
.on::<lsp_ext::SyntaxTree>(handlers::handle_syntax_tree)
|
||||
.on::<lsp_ext::ViewHir>(handlers::handle_view_hir)
|
||||
.on::<lsp_ext::ExpandMacro>(handlers::handle_expand_macro)
|
||||
.on::<lsp_ext::ParentModule>(handlers::handle_parent_module)
|
||||
.on::<lsp_ext::Runnables>(handlers::handle_runnables)
|
||||
|
|
|
@ -103,6 +103,11 @@
|
|||
"title": "Show Syntax Tree",
|
||||
"category": "Rust Analyzer"
|
||||
},
|
||||
{
|
||||
"command": "rust-analyzer.viewHir",
|
||||
"title": "View Hir",
|
||||
"category": "Rust Analyzer"
|
||||
},
|
||||
{
|
||||
"command": "rust-analyzer.expandMacro",
|
||||
"title": "Expand macro recursively",
|
||||
|
@ -998,6 +1003,10 @@
|
|||
"command": "rust-analyzer.syntaxTree",
|
||||
"when": "inRustProject"
|
||||
},
|
||||
{
|
||||
"command": "rust-analyzer.viewHir",
|
||||
"when": "inRustProject"
|
||||
},
|
||||
{
|
||||
"command": "rust-analyzer.expandMacro",
|
||||
"when": "inRustProject"
|
||||
|
|
|
@ -340,6 +340,75 @@ export function syntaxTree(ctx: Ctx): Cmd {
|
|||
};
|
||||
}
|
||||
|
||||
// Opens the virtual file that will show hir
|
||||
//
|
||||
// The contents of the file come from the `TextDocumentContentProvider`
|
||||
export function viewHir(ctx: Ctx): Cmd {
|
||||
const tdcp = new class implements vscode.TextDocumentContentProvider {
|
||||
readonly uri = vscode.Uri.parse('rust-analyzer://viewHir/hir.txt');
|
||||
readonly eventEmitter = new vscode.EventEmitter<vscode.Uri>();
|
||||
constructor() {
|
||||
vscode.workspace.onDidChangeTextDocument(this.onDidChangeTextDocument, this, ctx.subscriptions);
|
||||
vscode.window.onDidChangeActiveTextEditor(this.onDidChangeActiveTextEditor, this, ctx.subscriptions);
|
||||
}
|
||||
|
||||
private onDidChangeTextDocument(event: vscode.TextDocumentChangeEvent) {
|
||||
if (isRustDocument(event.document)) {
|
||||
// We need to order this after language server updates, but there's no API for that.
|
||||
// Hence, good old sleep().
|
||||
void sleep(10).then(() => this.eventEmitter.fire(this.uri));
|
||||
}
|
||||
}
|
||||
private onDidChangeActiveTextEditor(editor: vscode.TextEditor | undefined) {
|
||||
if (editor && isRustEditor(editor)) {
|
||||
this.eventEmitter.fire(this.uri);
|
||||
}
|
||||
}
|
||||
|
||||
provideTextDocumentContent(_uri: vscode.Uri, ct: vscode.CancellationToken): vscode.ProviderResult<string> {
|
||||
const rustEditor = ctx.activeRustEditor;
|
||||
const client = ctx.client;
|
||||
if (!rustEditor || !client) return '';
|
||||
|
||||
const params = {
|
||||
textDocument: client.code2ProtocolConverter.asTextDocumentIdentifier(rustEditor.document),
|
||||
position: client.code2ProtocolConverter.asPosition(
|
||||
rustEditor.selection.active,
|
||||
),
|
||||
};
|
||||
return client.sendRequest(ra.viewHir, params, ct);
|
||||
}
|
||||
|
||||
get onDidChange(): vscode.Event<vscode.Uri> {
|
||||
return this.eventEmitter.event;
|
||||
}
|
||||
};
|
||||
|
||||
void new AstInspector(ctx);
|
||||
|
||||
ctx.pushCleanup(vscode.workspace.registerTextDocumentContentProvider('rust-analyzer', tdcp));
|
||||
ctx.pushCleanup(vscode.languages.setLanguageConfiguration("ra_syntax_tree", {
|
||||
brackets: [["[", ")"]],
|
||||
}));
|
||||
|
||||
return async () => {
|
||||
const editor = vscode.window.activeTextEditor;
|
||||
const rangeEnabled = !!editor && !editor.selection.isEmpty;
|
||||
|
||||
const uri = rangeEnabled
|
||||
? vscode.Uri.parse(`${tdcp.uri.toString()}?range=true`)
|
||||
: tdcp.uri;
|
||||
|
||||
const document = await vscode.workspace.openTextDocument(uri);
|
||||
|
||||
tdcp.eventEmitter.fire(uri);
|
||||
|
||||
void await vscode.window.showTextDocument(document, {
|
||||
viewColumn: vscode.ViewColumn.Two,
|
||||
preserveFocus: true
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
// Opens the virtual file that will show the syntax tree
|
||||
//
|
||||
|
|
|
@ -24,6 +24,7 @@ export interface SyntaxTreeParams {
|
|||
}
|
||||
export const syntaxTree = new lc.RequestType<SyntaxTreeParams, string, void>("rust-analyzer/syntaxTree");
|
||||
|
||||
export const viewHir = new lc.RequestType<lc.TextDocumentPositionParams, string, void>("rust-analyzer/viewHir");
|
||||
|
||||
export interface ExpandMacroParams {
|
||||
textDocument: lc.TextDocumentIdentifier;
|
||||
|
|
|
@ -105,6 +105,7 @@ async function tryActivate(context: vscode.ExtensionContext) {
|
|||
ctx.registerCommand('joinLines', commands.joinLines);
|
||||
ctx.registerCommand('parentModule', commands.parentModule);
|
||||
ctx.registerCommand('syntaxTree', commands.syntaxTree);
|
||||
ctx.registerCommand('viewHir', commands.viewHir);
|
||||
ctx.registerCommand('expandMacro', commands.expandMacro);
|
||||
ctx.registerCommand('run', commands.run);
|
||||
ctx.registerCommand('debug', commands.debug);
|
||||
|
|
Loading…
Reference in a new issue