diff options
Diffstat (limited to 'crates/ra_ide/src/runnables.rs')
-rw-r--r-- | crates/ra_ide/src/runnables.rs | 113 |
1 files changed, 108 insertions, 5 deletions
diff --git a/crates/ra_ide/src/runnables.rs b/crates/ra_ide/src/runnables.rs index 38637c19c..131b8f307 100644 --- a/crates/ra_ide/src/runnables.rs +++ b/crates/ra_ide/src/runnables.rs | |||
@@ -1,6 +1,6 @@ | |||
1 | //! FIXME: write short doc here | 1 | //! FIXME: write short doc here |
2 | 2 | ||
3 | use hir::Semantics; | 3 | use hir::{AsAssocItem, Semantics}; |
4 | use itertools::Itertools; | 4 | use itertools::Itertools; |
5 | use ra_ide_db::RootDatabase; | 5 | use ra_ide_db::RootDatabase; |
6 | use ra_syntax::{ | 6 | use ra_syntax::{ |
@@ -9,6 +9,7 @@ use ra_syntax::{ | |||
9 | }; | 9 | }; |
10 | 10 | ||
11 | use crate::FileId; | 11 | use crate::FileId; |
12 | use ast::DocCommentsOwner; | ||
12 | use std::fmt::Display; | 13 | use std::fmt::Display; |
13 | 14 | ||
14 | #[derive(Debug)] | 15 | #[derive(Debug)] |
@@ -37,6 +38,7 @@ pub enum RunnableKind { | |||
37 | Test { test_id: TestId, attr: TestAttr }, | 38 | Test { test_id: TestId, attr: TestAttr }, |
38 | TestMod { path: String }, | 39 | TestMod { path: String }, |
39 | Bench { test_id: TestId }, | 40 | Bench { test_id: TestId }, |
41 | DocTest { test_id: TestId }, | ||
40 | Bin, | 42 | Bin, |
41 | } | 43 | } |
42 | 44 | ||
@@ -63,14 +65,36 @@ fn runnable_fn(sema: &Semantics<RootDatabase>, fn_def: ast::FnDef) -> Option<Run | |||
63 | RunnableKind::Bin | 65 | RunnableKind::Bin |
64 | } else { | 66 | } else { |
65 | let test_id = if let Some(module) = sema.to_def(&fn_def).map(|def| def.module(sema.db)) { | 67 | let test_id = if let Some(module) = sema.to_def(&fn_def).map(|def| def.module(sema.db)) { |
66 | let path = module | 68 | let def = sema.to_def(&fn_def)?; |
69 | let impl_trait_name = | ||
70 | def.as_assoc_item(sema.db).and_then(|assoc_item| { | ||
71 | match assoc_item.container(sema.db) { | ||
72 | hir::AssocItemContainer::Trait(trait_item) => { | ||
73 | Some(trait_item.name(sema.db).to_string()) | ||
74 | } | ||
75 | hir::AssocItemContainer::ImplDef(impl_def) => impl_def | ||
76 | .target_ty(sema.db) | ||
77 | .as_adt() | ||
78 | .map(|adt| adt.name(sema.db).to_string()), | ||
79 | } | ||
80 | }); | ||
81 | |||
82 | let path_iter = module | ||
67 | .path_to_root(sema.db) | 83 | .path_to_root(sema.db) |
68 | .into_iter() | 84 | .into_iter() |
69 | .rev() | 85 | .rev() |
70 | .filter_map(|it| it.name(sema.db)) | 86 | .filter_map(|it| it.name(sema.db)) |
71 | .map(|name| name.to_string()) | 87 | .map(|name| name.to_string()); |
72 | .chain(std::iter::once(name_string)) | 88 | |
73 | .join("::"); | 89 | let path = if let Some(impl_trait_name) = impl_trait_name { |
90 | path_iter | ||
91 | .chain(std::iter::once(impl_trait_name)) | ||
92 | .chain(std::iter::once(name_string)) | ||
93 | .join("::") | ||
94 | } else { | ||
95 | path_iter.chain(std::iter::once(name_string)).join("::") | ||
96 | }; | ||
97 | |||
74 | TestId::Path(path) | 98 | TestId::Path(path) |
75 | } else { | 99 | } else { |
76 | TestId::Name(name_string) | 100 | TestId::Name(name_string) |
@@ -81,6 +105,8 @@ fn runnable_fn(sema: &Semantics<RootDatabase>, fn_def: ast::FnDef) -> Option<Run | |||
81 | RunnableKind::Test { test_id, attr } | 105 | RunnableKind::Test { test_id, attr } |
82 | } else if fn_def.has_atom_attr("bench") { | 106 | } else if fn_def.has_atom_attr("bench") { |
83 | RunnableKind::Bench { test_id } | 107 | RunnableKind::Bench { test_id } |
108 | } else if has_doc_test(&fn_def) { | ||
109 | RunnableKind::DocTest { test_id } | ||
84 | } else { | 110 | } else { |
85 | return None; | 111 | return None; |
86 | } | 112 | } |
@@ -117,6 +143,10 @@ fn has_test_related_attribute(fn_def: &ast::FnDef) -> bool { | |||
117 | .any(|attribute_text| attribute_text.contains("test")) | 143 | .any(|attribute_text| attribute_text.contains("test")) |
118 | } | 144 | } |
119 | 145 | ||
146 | fn has_doc_test(fn_def: &ast::FnDef) -> bool { | ||
147 | fn_def.doc_comment_text().map_or(false, |comment| comment.contains("```")) | ||
148 | } | ||
149 | |||
120 | fn runnable_mod(sema: &Semantics<RootDatabase>, module: ast::Module) -> Option<Runnable> { | 150 | fn runnable_mod(sema: &Semantics<RootDatabase>, module: ast::Module) -> Option<Runnable> { |
121 | let has_test_function = module | 151 | let has_test_function = module |
122 | .item_list()? | 152 | .item_list()? |
@@ -195,6 +225,79 @@ mod tests { | |||
195 | } | 225 | } |
196 | 226 | ||
197 | #[test] | 227 | #[test] |
228 | fn test_runnables_doc_test() { | ||
229 | let (analysis, pos) = analysis_and_position( | ||
230 | r#" | ||
231 | //- /lib.rs | ||
232 | <|> //empty | ||
233 | fn main() {} | ||
234 | |||
235 | /// ``` | ||
236 | /// let x = 5; | ||
237 | /// ``` | ||
238 | fn foo() {} | ||
239 | "#, | ||
240 | ); | ||
241 | let runnables = analysis.runnables(pos.file_id).unwrap(); | ||
242 | assert_debug_snapshot!(&runnables, | ||
243 | @r###" | ||
244 | [ | ||
245 | Runnable { | ||
246 | range: 1..21, | ||
247 | kind: Bin, | ||
248 | }, | ||
249 | Runnable { | ||
250 | range: 22..64, | ||
251 | kind: DocTest { | ||
252 | test_id: Path( | ||
253 | "foo", | ||
254 | ), | ||
255 | }, | ||
256 | }, | ||
257 | ] | ||
258 | "### | ||
259 | ); | ||
260 | } | ||
261 | |||
262 | #[test] | ||
263 | fn test_runnables_doc_test_in_impl() { | ||
264 | let (analysis, pos) = analysis_and_position( | ||
265 | r#" | ||
266 | //- /lib.rs | ||
267 | <|> //empty | ||
268 | fn main() {} | ||
269 | |||
270 | struct Data; | ||
271 | impl Data { | ||
272 | /// ``` | ||
273 | /// let x = 5; | ||
274 | /// ``` | ||
275 | fn foo() {} | ||
276 | } | ||
277 | "#, | ||
278 | ); | ||
279 | let runnables = analysis.runnables(pos.file_id).unwrap(); | ||
280 | assert_debug_snapshot!(&runnables, | ||
281 | @r###" | ||
282 | [ | ||
283 | Runnable { | ||
284 | range: 1..21, | ||
285 | kind: Bin, | ||
286 | }, | ||
287 | Runnable { | ||
288 | range: 51..105, | ||
289 | kind: DocTest { | ||
290 | test_id: Path( | ||
291 | "Data::foo", | ||
292 | ), | ||
293 | }, | ||
294 | }, | ||
295 | ] | ||
296 | "### | ||
297 | ); | ||
298 | } | ||
299 | |||
300 | #[test] | ||
198 | fn test_runnables_module() { | 301 | fn test_runnables_module() { |
199 | let (analysis, pos) = analysis_and_position( | 302 | let (analysis, pos) = analysis_and_position( |
200 | r#" | 303 | r#" |