about summary refs log tree commit diff
path: root/crates/ide/src/interpret_function.rs
diff options
context:
space:
mode:
authorhkalbasi <hamidrezakalbasi@protonmail.com>2023-04-28 20:44:30 +0330
committerhkalbasi <hamidrezakalbasi@protonmail.com>2023-05-01 23:23:10 +0330
commit6312fbf521e42e5a5ff193ceee6a8c7735be3a45 (patch)
treecbaea739cd9f5e5c850d01c2f2b232da39076668 /crates/ide/src/interpret_function.rs
parent001607fdb4ac6a3059813451234097ce7c2f35de (diff)
downloadrust-6312fbf521e42e5a5ff193ceee6a8c7735be3a45.tar.gz
rust-6312fbf521e42e5a5ff193ceee6a8c7735be3a45.zip
MIR episode 4
Diffstat (limited to 'crates/ide/src/interpret_function.rs')
-rw-r--r--crates/ide/src/interpret_function.rs49
1 files changed, 49 insertions, 0 deletions
diff --git a/crates/ide/src/interpret_function.rs b/crates/ide/src/interpret_function.rs
new file mode 100644
index 00000000000..d111f98955a
--- /dev/null
+++ b/crates/ide/src/interpret_function.rs
@@ -0,0 +1,49 @@
+use hir::Semantics;
+use ide_db::base_db::SourceDatabaseExt;
+use ide_db::RootDatabase;
+use ide_db::{base_db::FilePosition, LineIndexDatabase};
+use std::{fmt::Write, time::Instant};
+use syntax::TextRange;
+use syntax::{algo::find_node_at_offset, ast, AstNode};
+
+// Feature: Interpret Function
+//
+// |===
+// | Editor  | Action Name
+//
+// | VS Code | **rust-analyzer: Interpret Function**
+// |===
+pub(crate) fn interpret_function(db: &RootDatabase, position: FilePosition) -> String {
+    let start_time = Instant::now();
+    let mut result = find_and_interpret(db, position)
+        .unwrap_or_else(|| "Not inside a function body".to_string());
+    let duration = Instant::now() - start_time;
+    writeln!(result, "").unwrap();
+    writeln!(result, "----------------------").unwrap();
+    writeln!(result, "  Finished in {}s", duration.as_secs_f32()).unwrap();
+    result
+}
+
+fn find_and_interpret(db: &RootDatabase, position: FilePosition) -> Option<String> {
+    let sema = Semantics::new(db);
+    let source_file = sema.parse(position.file_id);
+
+    let item = find_node_at_offset::<ast::Item>(source_file.syntax(), position.offset)?;
+    let def = match item {
+        ast::Item::Fn(it) => sema.to_def(&it)?,
+        _ => return None,
+    };
+    let span_formatter = |file_id, text_range: TextRange| {
+        let line_col = db.line_index(file_id).line_col(text_range.start());
+        let path = &db
+            .source_root(db.file_source_root(file_id))
+            .path_for_file(&file_id)
+            .map(|x| x.to_string());
+        let path = path.as_deref().unwrap_or("<unknown file>");
+        format!("file://{path}#{}:{}", line_col.line + 1, line_col.col)
+    };
+    match def.eval(db, span_formatter) {
+        Ok(_) => Some("pass".to_string()),
+        Err(e) => Some(e),
+    }
+}