aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_ide/src/runnables.rs
diff options
context:
space:
mode:
authorAleksey Kladov <[email protected]>2020-02-18 17:35:10 +0000
committerAleksey Kladov <[email protected]>2020-02-26 11:55:50 +0000
commitc3a4c4429de83450654795534e64e878a774a088 (patch)
tree12d89798f61b276f8bd640db07276a7d4e92b1c2 /crates/ra_ide/src/runnables.rs
parent04deae3dba7c9b7054f7a1d64e4b93a05aecc132 (diff)
Refactor primary IDE API
This introduces the new type -- Semantics. Semantics maps SyntaxNodes to various semantic info, such as type, name resolution or macro expansions. To do so, Semantics maintains a HashMap which maps every node it saw to the file from which the node originated. This is enough to get all the necessary hir bits just from syntax.
Diffstat (limited to 'crates/ra_ide/src/runnables.rs')
-rw-r--r--crates/ra_ide/src/runnables.rs50
1 files changed, 16 insertions, 34 deletions
diff --git a/crates/ra_ide/src/runnables.rs b/crates/ra_ide/src/runnables.rs
index be2a67d0a..74877e90f 100644
--- a/crates/ra_ide/src/runnables.rs
+++ b/crates/ra_ide/src/runnables.rs
@@ -1,8 +1,7 @@
1//! FIXME: write short doc here 1//! FIXME: write short doc here
2 2
3use hir::{InFile, SourceBinder}; 3use hir::Semantics;
4use itertools::Itertools; 4use itertools::Itertools;
5use ra_db::SourceDatabase;
6use ra_ide_db::RootDatabase; 5use ra_ide_db::RootDatabase;
7use ra_syntax::{ 6use ra_syntax::{
8 ast::{self, AstNode, AttrsOwner, ModuleItemOwner, NameOwner}, 7 ast::{self, AstNode, AttrsOwner, ModuleItemOwner, NameOwner},
@@ -42,46 +41,33 @@ pub enum RunnableKind {
42} 41}
43 42
44pub(crate) fn runnables(db: &RootDatabase, file_id: FileId) -> Vec<Runnable> { 43pub(crate) fn runnables(db: &RootDatabase, file_id: FileId) -> Vec<Runnable> {
45 let parse = db.parse(file_id); 44 let sema = Semantics::new(db);
46 let mut sb = SourceBinder::new(db); 45 let source_file = sema.parse(file_id);
47 parse.tree().syntax().descendants().filter_map(|i| runnable(db, &mut sb, file_id, i)).collect() 46 source_file.syntax().descendants().filter_map(|i| runnable(&sema, i)).collect()
48} 47}
49 48
50fn runnable( 49fn runnable(sema: &Semantics<RootDatabase>, item: SyntaxNode) -> Option<Runnable> {
51 db: &RootDatabase,
52 source_binder: &mut SourceBinder<RootDatabase>,
53 file_id: FileId,
54 item: SyntaxNode,
55) -> Option<Runnable> {
56 match_ast! { 50 match_ast! {
57 match item { 51 match item {
58 ast::FnDef(it) => { runnable_fn(db, source_binder, file_id, it) }, 52 ast::FnDef(it) => { runnable_fn(sema, it) },
59 ast::Module(it) => { runnable_mod(db, source_binder, file_id, it) }, 53 ast::Module(it) => { runnable_mod(sema, it) },
60 _ => { None }, 54 _ => None,
61 } 55 }
62 } 56 }
63} 57}
64 58
65fn runnable_fn( 59fn runnable_fn(sema: &Semantics<RootDatabase>, fn_def: ast::FnDef) -> Option<Runnable> {
66 db: &RootDatabase,
67 source_binder: &mut SourceBinder<RootDatabase>,
68 file_id: FileId,
69 fn_def: ast::FnDef,
70) -> Option<Runnable> {
71 let name_string = fn_def.name()?.text().to_string(); 60 let name_string = fn_def.name()?.text().to_string();
72 61
73 let kind = if name_string == "main" { 62 let kind = if name_string == "main" {
74 RunnableKind::Bin 63 RunnableKind::Bin
75 } else { 64 } else {
76 let test_id = if let Some(module) = source_binder 65 let test_id = if let Some(module) = sema.to_def(&fn_def).map(|def| def.module(sema.db)) {
77 .to_def(InFile::new(file_id.into(), fn_def.clone()))
78 .map(|def| def.module(db))
79 {
80 let path = module 66 let path = module
81 .path_to_root(db) 67 .path_to_root(sema.db)
82 .into_iter() 68 .into_iter()
83 .rev() 69 .rev()
84 .filter_map(|it| it.name(db)) 70 .filter_map(|it| it.name(sema.db))
85 .map(|name| name.to_string()) 71 .map(|name| name.to_string())
86 .chain(std::iter::once(name_string)) 72 .chain(std::iter::once(name_string))
87 .join("::"); 73 .join("::");
@@ -115,12 +101,7 @@ fn has_test_related_attribute(fn_def: &ast::FnDef) -> bool {
115 .any(|attribute_text| attribute_text.contains("test")) 101 .any(|attribute_text| attribute_text.contains("test"))
116} 102}
117 103
118fn runnable_mod( 104fn runnable_mod(sema: &Semantics<RootDatabase>, module: ast::Module) -> Option<Runnable> {
119 db: &RootDatabase,
120 source_binder: &mut SourceBinder<RootDatabase>,
121 file_id: FileId,
122 module: ast::Module,
123) -> Option<Runnable> {
124 let has_test_function = module 105 let has_test_function = module
125 .item_list()? 106 .item_list()?
126 .items() 107 .items()
@@ -133,9 +114,10 @@ fn runnable_mod(
133 return None; 114 return None;
134 } 115 }
135 let range = module.syntax().text_range(); 116 let range = module.syntax().text_range();
136 let module = source_binder.to_def(InFile::new(file_id.into(), module))?; 117 let module = sema.to_def(&module)?;
137 118
138 let path = module.path_to_root(db).into_iter().rev().filter_map(|it| it.name(db)).join("::"); 119 let path =
120 module.path_to_root(sema.db).into_iter().rev().filter_map(|it| it.name(sema.db)).join("::");
139 Some(Runnable { range, kind: RunnableKind::TestMod { path } }) 121 Some(Runnable { range, kind: RunnableKind::TestMod { path } })
140} 122}
141 123