Unnamed repository; edit this file 'description' to name the repository.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
use hir::{DefWithBody, Semantics};
use ide_db::base_db::FilePosition;
use ide_db::RootDatabase;
use syntax::{algo::ancestors_at_offset, ast, AstNode};

// Feature: View Mir
//
// |===
// | Editor  | Action Name
//
// | VS Code | **rust-analyzer: View Mir**
// |===
pub(crate) fn view_mir(db: &RootDatabase, position: FilePosition) -> String {
    body_mir(db, position).unwrap_or_else(|| "Not inside a function body".to_owned())
}

fn body_mir(db: &RootDatabase, position: FilePosition) -> Option<String> {
    let sema = Semantics::new(db);
    let source_file = sema.parse(position.file_id);

    let item = ancestors_at_offset(source_file.syntax(), position.offset)
        .filter(|it| !ast::MacroCall::can_cast(it.kind()))
        .find_map(ast::Item::cast)?;
    let def: DefWithBody = match item {
        ast::Item::Fn(it) => sema.to_def(&it)?.into(),
        ast::Item::Const(it) => sema.to_def(&it)?.into(),
        ast::Item::Static(it) => sema.to_def(&it)?.into(),
        _ => return None,
    };
    Some(def.debug_mir(db))
}
nd_map(ast::Stmt::cast).ok_or(())?; if !s.ends_with(';') && node.to_string().ends_with(';') { node = node.clone_for_update(); if let Some(it) = node.syntax().last_token() { it.detach() } } if node.to_string() != s { return Err(()); } Ok(node.syntax().clone_subtree()) } fn fragment<T: AstNode>(template: &str, s: &str) -> Result<SyntaxNode, ()> { let s = s.trim(); let input = template.replace("{}", s); let parse = syntax::SourceFile::parse(&input, syntax::Edition::CURRENT); if !parse.errors().is_empty() { return Err(()); } let node = parse.tree().syntax().descendants().find_map(T::cast).ok_or(())?; if node.syntax().text() != s { return Err(()); } Ok(node.syntax().clone_subtree()) }