From 28f6eedba59d3a5dd43fe6fbde3d19d54d0e2f9d Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Wed, 2 Jan 2019 20:12:38 +0300 Subject: simplify runnables --- crates/ra_analysis/src/imp.rs | 21 ------- crates/ra_analysis/src/lib.rs | 7 +-- crates/ra_analysis/src/runnables.rs | 106 ++++++++++++++++++++---------------- 3 files changed, 61 insertions(+), 73 deletions(-) (limited to 'crates/ra_analysis/src') diff --git a/crates/ra_analysis/src/imp.rs b/crates/ra_analysis/src/imp.rs index 0faf8b85d..ff13247de 100644 --- a/crates/ra_analysis/src/imp.rs +++ b/crates/ra_analysis/src/imp.rs @@ -100,27 +100,6 @@ impl db::RootDatabase { } impl db::RootDatabase { - pub(crate) fn module_path(&self, position: FilePosition) -> Cancelable> { - let descr = match source_binder::module_from_position(self, position)? { - None => return Ok(None), - Some(it) => it, - }; - let name = match descr.name() { - None => return Ok(None), - Some(it) => it.to_string(), - }; - - let modules = descr.path_to_root(); - - let path = modules - .iter() - .filter_map(|s| s.name()) - .skip(1) // name is already part of the string. - .fold(name, |path, it| format!("{}::{}", it, path)); - - Ok(Some(path.to_string())) - } - /// This returns `Vec` because a module may be included from several places. We /// don't handle this case yet though, so the Vec has length at most one. pub(crate) fn parent_module( diff --git a/crates/ra_analysis/src/lib.rs b/crates/ra_analysis/src/lib.rs index 54eb2f4d3..a01febf4e 100644 --- a/crates/ra_analysis/src/lib.rs +++ b/crates/ra_analysis/src/lib.rs @@ -382,10 +382,6 @@ impl Analysis { pub fn parent_module(&self, position: FilePosition) -> Cancelable> { self.db.parent_module(position) } - /// Returns `::` separated path to the current module from the crate root. - pub fn module_path(&self, position: FilePosition) -> Cancelable> { - self.db.module_path(position) - } /// Returns crates this file belongs too. pub fn crate_for(&self, file_id: FileId) -> Cancelable> { self.db.crate_for(file_id) @@ -396,8 +392,7 @@ impl Analysis { } /// Returns the set of possible targets to run for the current file. pub fn runnables(&self, file_id: FileId) -> Cancelable> { - let file = self.db.source_file(file_id); - Ok(runnables::runnables(self, &file, file_id)) + runnables::runnables(&*self.db, file_id) } /// Computes syntax highlighting for the given file. pub fn highlight(&self, file_id: FileId) -> Cancelable> { diff --git a/crates/ra_analysis/src/runnables.rs b/crates/ra_analysis/src/runnables.rs index 61ca0930a..474267605 100644 --- a/crates/ra_analysis/src/runnables.rs +++ b/crates/ra_analysis/src/runnables.rs @@ -1,11 +1,11 @@ +use itertools::Itertools; use ra_syntax::{ ast::{self, AstNode, NameOwner, ModuleItemOwner}, - SourceFileNode, TextRange, SyntaxNodeRef, - TextUnit, -}; -use crate::{ - Analysis, FileId, FilePosition + TextRange, SyntaxNodeRef, }; +use ra_db::{Cancelable, SyntaxDatabase}; + +use crate::{db::RootDatabase, FileId}; #[derive(Debug)] pub struct Runnable { @@ -20,53 +20,67 @@ pub enum RunnableKind { Bin, } -pub fn runnables( - analysis: &Analysis, - file_node: &SourceFileNode, - file_id: FileId, -) -> Vec { - file_node +pub(crate) fn runnables(db: &RootDatabase, file_id: FileId) -> Cancelable> { + let source_file = db.source_file(file_id); + let res = source_file .syntax() .descendants() - .filter_map(|i| runnable(analysis, i, file_id)) - .collect() + .filter_map(|i| runnable(db, file_id, i)) + .collect(); + Ok(res) } -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, - }) +fn runnable(db: &RootDatabase, file_id: FileId, item: SyntaxNodeRef) -> Option { + if let Some(fn_def) = ast::FnDef::cast(item) { + runnable_fn(fn_def) } 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 - } + runnable_mod(db, file_id, m) } else { None } } + +fn runnable_fn(fn_def: ast::FnDef) -> Option { + let name = fn_def.name()?.text(); + let kind = if name == "main" { + RunnableKind::Bin + } else if fn_def.has_atom_attr("test") { + RunnableKind::Test { + name: name.to_string(), + } + } else { + return None; + }; + Some(Runnable { + range: fn_def.syntax().range(), + kind, + }) +} + +fn runnable_mod(db: &RootDatabase, file_id: FileId, module: ast::Module) -> Option { + let has_test_function = module + .item_list()? + .items() + .filter_map(|it| match it { + ast::ModuleItem::FnDef(it) => Some(it), + _ => None, + }) + .any(|f| f.has_atom_attr("test")); + if !has_test_function { + return None; + } + let range = module.syntax().range(); + let module = + hir::source_binder::module_from_child_node(db, file_id, module.syntax()).ok()??; + let path = module + .path_to_root() + .into_iter() + .rev() + .into_iter() + .filter_map(|it| it.name().map(Clone::clone)) + .join("::"); + Some(Runnable { + range, + kind: RunnableKind::TestMod { path }, + }) +} -- cgit v1.2.3