From 05daa86634b41aa3f311a1ac0b02bf7fed7ed569 Mon Sep 17 00:00:00 2001 From: Jan Jansen Date: Thu, 27 Dec 2018 21:45:16 +0100 Subject: Make modules with tests runnable Fixes #154 --- crates/ra_analysis/src/runnables.rs | 72 +++++++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 crates/ra_analysis/src/runnables.rs (limited to 'crates/ra_analysis/src/runnables.rs') diff --git a/crates/ra_analysis/src/runnables.rs b/crates/ra_analysis/src/runnables.rs new file mode 100644 index 000000000..61ca0930a --- /dev/null +++ b/crates/ra_analysis/src/runnables.rs @@ -0,0 +1,72 @@ +use ra_syntax::{ + ast::{self, AstNode, NameOwner, ModuleItemOwner}, + SourceFileNode, TextRange, SyntaxNodeRef, + TextUnit, +}; +use crate::{ + Analysis, FileId, FilePosition +}; + +#[derive(Debug)] +pub struct Runnable { + pub range: TextRange, + pub kind: RunnableKind, +} + +#[derive(Debug)] +pub enum RunnableKind { + Test { name: String }, + TestMod { path: String }, + Bin, +} + +pub fn runnables( + analysis: &Analysis, + file_node: &SourceFileNode, + file_id: FileId, +) -> Vec { + file_node + .syntax() + .descendants() + .filter_map(|i| runnable(analysis, i, file_id)) + .collect() +} + +fn runnable<'a>(analysis: &Analysis, item: SyntaxNodeRef<'a>, file_id: FileId) -> Option { + if let Some(f) = ast::FnDef::cast(item) { + let name = f.name()?.text(); + let kind = if name == "main" { + RunnableKind::Bin + } else if f.has_atom_attr("test") { + RunnableKind::Test { + name: name.to_string(), + } + } else { + return None; + }; + Some(Runnable { + range: f.syntax().range(), + kind, + }) + } else if let Some(m) = ast::Module::cast(item) { + if m.item_list()? + .items() + .map(ast::ModuleItem::syntax) + .filter_map(ast::FnDef::cast) + .any(|f| f.has_atom_attr("test")) + { + let postition = FilePosition { + file_id, + offset: m.syntax().range().start() + TextUnit::from_usize(1), + }; + analysis.module_path(postition).ok()?.map(|path| Runnable { + range: m.syntax().range(), + kind: RunnableKind::TestMod { path }, + }) + } else { + None + } + } else { + None + } +} -- cgit v1.2.3