diff options
Diffstat (limited to 'crates/ra_ide/src/runnables.rs')
-rw-r--r-- | crates/ra_ide/src/runnables.rs | 261 |
1 files changed, 233 insertions, 28 deletions
diff --git a/crates/ra_ide/src/runnables.rs b/crates/ra_ide/src/runnables.rs index 6e7e47199..f32ce0d22 100644 --- a/crates/ra_ide/src/runnables.rs +++ b/crates/ra_ide/src/runnables.rs | |||
@@ -1,21 +1,19 @@ | |||
1 | //! FIXME: write short doc here | 1 | use std::fmt; |
2 | 2 | ||
3 | use hir::{AsAssocItem, Attrs, HirFileId, InFile, Semantics}; | 3 | use hir::{AsAssocItem, Attrs, HirFileId, InFile, Semantics}; |
4 | use itertools::Itertools; | 4 | use itertools::Itertools; |
5 | use ra_cfg::CfgExpr; | ||
5 | use ra_ide_db::RootDatabase; | 6 | use ra_ide_db::RootDatabase; |
6 | use ra_syntax::{ | 7 | use ra_syntax::{ |
7 | ast::{self, AstNode, AttrsOwner, ModuleItemOwner, NameOwner}, | 8 | ast::{self, AstNode, AttrsOwner, DocCommentsOwner, ModuleItemOwner, NameOwner}, |
8 | match_ast, SyntaxNode, TextRange, | 9 | match_ast, SyntaxNode, |
9 | }; | 10 | }; |
10 | 11 | ||
11 | use crate::FileId; | 12 | use crate::{display::ToNav, FileId, NavigationTarget}; |
12 | use ast::DocCommentsOwner; | ||
13 | use ra_cfg::CfgExpr; | ||
14 | use std::fmt::Display; | ||
15 | 13 | ||
16 | #[derive(Debug)] | 14 | #[derive(Debug)] |
17 | pub struct Runnable { | 15 | pub struct Runnable { |
18 | pub range: TextRange, | 16 | pub nav: NavigationTarget, |
19 | pub kind: RunnableKind, | 17 | pub kind: RunnableKind, |
20 | pub cfg_exprs: Vec<CfgExpr>, | 18 | pub cfg_exprs: Vec<CfgExpr>, |
21 | } | 19 | } |
@@ -26,8 +24,8 @@ pub enum TestId { | |||
26 | Path(String), | 24 | Path(String), |
27 | } | 25 | } |
28 | 26 | ||
29 | impl Display for TestId { | 27 | impl fmt::Display for TestId { |
30 | fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { | 28 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
31 | match self { | 29 | match self { |
32 | TestId::Name(name) => write!(f, "{}", name), | 30 | TestId::Name(name) => write!(f, "{}", name), |
33 | TestId::Path(path) => write!(f, "{}", path), | 31 | TestId::Path(path) => write!(f, "{}", path), |
@@ -44,6 +42,17 @@ pub enum RunnableKind { | |||
44 | Bin, | 42 | Bin, |
45 | } | 43 | } |
46 | 44 | ||
45 | // Feature: Run | ||
46 | // | ||
47 | // Shows a popup suggesting to run a test/benchmark/binary **at the current cursor | ||
48 | // location**. Super useful for repeatedly running just a single test. Do bind this | ||
49 | // to a shortcut! | ||
50 | // | ||
51 | // |=== | ||
52 | // | Editor | Action Name | ||
53 | // | ||
54 | // | VS Code | **Rust Analyzer: Run** | ||
55 | // |=== | ||
47 | pub(crate) fn runnables(db: &RootDatabase, file_id: FileId) -> Vec<Runnable> { | 56 | pub(crate) fn runnables(db: &RootDatabase, file_id: FileId) -> Vec<Runnable> { |
48 | let sema = Semantics::new(db); | 57 | let sema = Semantics::new(db); |
49 | let source_file = sema.parse(file_id); | 58 | let source_file = sema.parse(file_id); |
@@ -122,7 +131,8 @@ fn runnable_fn( | |||
122 | let cfg_exprs = | 131 | let cfg_exprs = |
123 | attrs.by_key("cfg").tt_values().map(|subtree| ra_cfg::parse_cfg(subtree)).collect(); | 132 | attrs.by_key("cfg").tt_values().map(|subtree| ra_cfg::parse_cfg(subtree)).collect(); |
124 | 133 | ||
125 | Some(Runnable { range: fn_def.syntax().text_range(), kind, cfg_exprs }) | 134 | let nav = NavigationTarget::from_named(sema.db, InFile::new(file_id.into(), &fn_def)); |
135 | Some(Runnable { nav, kind, cfg_exprs }) | ||
126 | } | 136 | } |
127 | 137 | ||
128 | #[derive(Debug)] | 138 | #[derive(Debug)] |
@@ -174,7 +184,6 @@ fn runnable_mod( | |||
174 | if !has_test_function { | 184 | if !has_test_function { |
175 | return None; | 185 | return None; |
176 | } | 186 | } |
177 | let range = module.syntax().text_range(); | ||
178 | let module_def = sema.to_def(&module)?; | 187 | let module_def = sema.to_def(&module)?; |
179 | 188 | ||
180 | let path = module_def | 189 | let path = module_def |
@@ -188,7 +197,8 @@ fn runnable_mod( | |||
188 | let cfg_exprs = | 197 | let cfg_exprs = |
189 | attrs.by_key("cfg").tt_values().map(|subtree| ra_cfg::parse_cfg(subtree)).collect(); | 198 | attrs.by_key("cfg").tt_values().map(|subtree| ra_cfg::parse_cfg(subtree)).collect(); |
190 | 199 | ||
191 | Some(Runnable { range, kind: RunnableKind::TestMod { path }, cfg_exprs }) | 200 | let nav = module_def.to_nav(sema.db); |
201 | Some(Runnable { nav, kind: RunnableKind::TestMod { path }, cfg_exprs }) | ||
192 | } | 202 | } |
193 | 203 | ||
194 | #[cfg(test)] | 204 | #[cfg(test)] |
@@ -218,12 +228,38 @@ mod tests { | |||
218 | @r###" | 228 | @r###" |
219 | [ | 229 | [ |
220 | Runnable { | 230 | Runnable { |
221 | range: 1..21, | 231 | nav: NavigationTarget { |
232 | file_id: FileId( | ||
233 | 1, | ||
234 | ), | ||
235 | full_range: 1..21, | ||
236 | name: "main", | ||
237 | kind: FN_DEF, | ||
238 | focus_range: Some( | ||
239 | 12..16, | ||
240 | ), | ||
241 | container_name: None, | ||
242 | description: None, | ||
243 | docs: None, | ||
244 | }, | ||
222 | kind: Bin, | 245 | kind: Bin, |
223 | cfg_exprs: [], | 246 | cfg_exprs: [], |
224 | }, | 247 | }, |
225 | Runnable { | 248 | Runnable { |
226 | range: 22..46, | 249 | nav: NavigationTarget { |
250 | file_id: FileId( | ||
251 | 1, | ||
252 | ), | ||
253 | full_range: 22..46, | ||
254 | name: "test_foo", | ||
255 | kind: FN_DEF, | ||
256 | focus_range: Some( | ||
257 | 33..41, | ||
258 | ), | ||
259 | container_name: None, | ||
260 | description: None, | ||
261 | docs: None, | ||
262 | }, | ||
227 | kind: Test { | 263 | kind: Test { |
228 | test_id: Path( | 264 | test_id: Path( |
229 | "test_foo", | 265 | "test_foo", |
@@ -235,7 +271,20 @@ mod tests { | |||
235 | cfg_exprs: [], | 271 | cfg_exprs: [], |
236 | }, | 272 | }, |
237 | Runnable { | 273 | Runnable { |
238 | range: 47..81, | 274 | nav: NavigationTarget { |
275 | file_id: FileId( | ||
276 | 1, | ||
277 | ), | ||
278 | full_range: 47..81, | ||
279 | name: "test_foo", | ||
280 | kind: FN_DEF, | ||
281 | focus_range: Some( | ||
282 | 68..76, | ||
283 | ), | ||
284 | container_name: None, | ||
285 | description: None, | ||
286 | docs: None, | ||
287 | }, | ||
239 | kind: Test { | 288 | kind: Test { |
240 | test_id: Path( | 289 | test_id: Path( |
241 | "test_foo", | 290 | "test_foo", |
@@ -270,12 +319,38 @@ mod tests { | |||
270 | @r###" | 319 | @r###" |
271 | [ | 320 | [ |
272 | Runnable { | 321 | Runnable { |
273 | range: 1..21, | 322 | nav: NavigationTarget { |
323 | file_id: FileId( | ||
324 | 1, | ||
325 | ), | ||
326 | full_range: 1..21, | ||
327 | name: "main", | ||
328 | kind: FN_DEF, | ||
329 | focus_range: Some( | ||
330 | 12..16, | ||
331 | ), | ||
332 | container_name: None, | ||
333 | description: None, | ||
334 | docs: None, | ||
335 | }, | ||
274 | kind: Bin, | 336 | kind: Bin, |
275 | cfg_exprs: [], | 337 | cfg_exprs: [], |
276 | }, | 338 | }, |
277 | Runnable { | 339 | Runnable { |
278 | range: 22..64, | 340 | nav: NavigationTarget { |
341 | file_id: FileId( | ||
342 | 1, | ||
343 | ), | ||
344 | full_range: 22..64, | ||
345 | name: "foo", | ||
346 | kind: FN_DEF, | ||
347 | focus_range: Some( | ||
348 | 56..59, | ||
349 | ), | ||
350 | container_name: None, | ||
351 | description: None, | ||
352 | docs: None, | ||
353 | }, | ||
279 | kind: DocTest { | 354 | kind: DocTest { |
280 | test_id: Path( | 355 | test_id: Path( |
281 | "foo", | 356 | "foo", |
@@ -310,12 +385,38 @@ mod tests { | |||
310 | @r###" | 385 | @r###" |
311 | [ | 386 | [ |
312 | Runnable { | 387 | Runnable { |
313 | range: 1..21, | 388 | nav: NavigationTarget { |
389 | file_id: FileId( | ||
390 | 1, | ||
391 | ), | ||
392 | full_range: 1..21, | ||
393 | name: "main", | ||
394 | kind: FN_DEF, | ||
395 | focus_range: Some( | ||
396 | 12..16, | ||
397 | ), | ||
398 | container_name: None, | ||
399 | description: None, | ||
400 | docs: None, | ||
401 | }, | ||
314 | kind: Bin, | 402 | kind: Bin, |
315 | cfg_exprs: [], | 403 | cfg_exprs: [], |
316 | }, | 404 | }, |
317 | Runnable { | 405 | Runnable { |
318 | range: 51..105, | 406 | nav: NavigationTarget { |
407 | file_id: FileId( | ||
408 | 1, | ||
409 | ), | ||
410 | full_range: 51..105, | ||
411 | name: "foo", | ||
412 | kind: FN_DEF, | ||
413 | focus_range: Some( | ||
414 | 97..100, | ||
415 | ), | ||
416 | container_name: None, | ||
417 | description: None, | ||
418 | docs: None, | ||
419 | }, | ||
319 | kind: DocTest { | 420 | kind: DocTest { |
320 | test_id: Path( | 421 | test_id: Path( |
321 | "Data::foo", | 422 | "Data::foo", |
@@ -345,14 +446,40 @@ mod tests { | |||
345 | @r###" | 446 | @r###" |
346 | [ | 447 | [ |
347 | Runnable { | 448 | Runnable { |
348 | range: 1..59, | 449 | nav: NavigationTarget { |
450 | file_id: FileId( | ||
451 | 1, | ||
452 | ), | ||
453 | full_range: 1..59, | ||
454 | name: "test_mod", | ||
455 | kind: MODULE, | ||
456 | focus_range: Some( | ||
457 | 13..21, | ||
458 | ), | ||
459 | container_name: None, | ||
460 | description: None, | ||
461 | docs: None, | ||
462 | }, | ||
349 | kind: TestMod { | 463 | kind: TestMod { |
350 | path: "test_mod", | 464 | path: "test_mod", |
351 | }, | 465 | }, |
352 | cfg_exprs: [], | 466 | cfg_exprs: [], |
353 | }, | 467 | }, |
354 | Runnable { | 468 | Runnable { |
355 | range: 28..57, | 469 | nav: NavigationTarget { |
470 | file_id: FileId( | ||
471 | 1, | ||
472 | ), | ||
473 | full_range: 28..57, | ||
474 | name: "test_foo1", | ||
475 | kind: FN_DEF, | ||
476 | focus_range: Some( | ||
477 | 43..52, | ||
478 | ), | ||
479 | container_name: None, | ||
480 | description: None, | ||
481 | docs: None, | ||
482 | }, | ||
356 | kind: Test { | 483 | kind: Test { |
357 | test_id: Path( | 484 | test_id: Path( |
358 | "test_mod::test_foo1", | 485 | "test_mod::test_foo1", |
@@ -387,14 +514,40 @@ mod tests { | |||
387 | @r###" | 514 | @r###" |
388 | [ | 515 | [ |
389 | Runnable { | 516 | Runnable { |
390 | range: 23..85, | 517 | nav: NavigationTarget { |
518 | file_id: FileId( | ||
519 | 1, | ||
520 | ), | ||
521 | full_range: 23..85, | ||
522 | name: "test_mod", | ||
523 | kind: MODULE, | ||
524 | focus_range: Some( | ||
525 | 27..35, | ||
526 | ), | ||
527 | container_name: None, | ||
528 | description: None, | ||
529 | docs: None, | ||
530 | }, | ||
391 | kind: TestMod { | 531 | kind: TestMod { |
392 | path: "foo::test_mod", | 532 | path: "foo::test_mod", |
393 | }, | 533 | }, |
394 | cfg_exprs: [], | 534 | cfg_exprs: [], |
395 | }, | 535 | }, |
396 | Runnable { | 536 | Runnable { |
397 | range: 46..79, | 537 | nav: NavigationTarget { |
538 | file_id: FileId( | ||
539 | 1, | ||
540 | ), | ||
541 | full_range: 46..79, | ||
542 | name: "test_foo1", | ||
543 | kind: FN_DEF, | ||
544 | focus_range: Some( | ||
545 | 65..74, | ||
546 | ), | ||
547 | container_name: None, | ||
548 | description: None, | ||
549 | docs: None, | ||
550 | }, | ||
398 | kind: Test { | 551 | kind: Test { |
399 | test_id: Path( | 552 | test_id: Path( |
400 | "foo::test_mod::test_foo1", | 553 | "foo::test_mod::test_foo1", |
@@ -431,14 +584,40 @@ mod tests { | |||
431 | @r###" | 584 | @r###" |
432 | [ | 585 | [ |
433 | Runnable { | 586 | Runnable { |
434 | range: 41..115, | 587 | nav: NavigationTarget { |
588 | file_id: FileId( | ||
589 | 1, | ||
590 | ), | ||
591 | full_range: 41..115, | ||
592 | name: "test_mod", | ||
593 | kind: MODULE, | ||
594 | focus_range: Some( | ||
595 | 45..53, | ||
596 | ), | ||
597 | container_name: None, | ||
598 | description: None, | ||
599 | docs: None, | ||
600 | }, | ||
435 | kind: TestMod { | 601 | kind: TestMod { |
436 | path: "foo::bar::test_mod", | 602 | path: "foo::bar::test_mod", |
437 | }, | 603 | }, |
438 | cfg_exprs: [], | 604 | cfg_exprs: [], |
439 | }, | 605 | }, |
440 | Runnable { | 606 | Runnable { |
441 | range: 68..105, | 607 | nav: NavigationTarget { |
608 | file_id: FileId( | ||
609 | 1, | ||
610 | ), | ||
611 | full_range: 68..105, | ||
612 | name: "test_foo1", | ||
613 | kind: FN_DEF, | ||
614 | focus_range: Some( | ||
615 | 91..100, | ||
616 | ), | ||
617 | container_name: None, | ||
618 | description: None, | ||
619 | docs: None, | ||
620 | }, | ||
442 | kind: Test { | 621 | kind: Test { |
443 | test_id: Path( | 622 | test_id: Path( |
444 | "foo::bar::test_mod::test_foo1", | 623 | "foo::bar::test_mod::test_foo1", |
@@ -470,7 +649,20 @@ mod tests { | |||
470 | @r###" | 649 | @r###" |
471 | [ | 650 | [ |
472 | Runnable { | 651 | Runnable { |
473 | range: 1..58, | 652 | nav: NavigationTarget { |
653 | file_id: FileId( | ||
654 | 1, | ||
655 | ), | ||
656 | full_range: 1..58, | ||
657 | name: "test_foo1", | ||
658 | kind: FN_DEF, | ||
659 | focus_range: Some( | ||
660 | 44..53, | ||
661 | ), | ||
662 | container_name: None, | ||
663 | description: None, | ||
664 | docs: None, | ||
665 | }, | ||
474 | kind: Test { | 666 | kind: Test { |
475 | test_id: Path( | 667 | test_id: Path( |
476 | "test_foo1", | 668 | "test_foo1", |
@@ -507,7 +699,20 @@ mod tests { | |||
507 | @r###" | 699 | @r###" |
508 | [ | 700 | [ |
509 | Runnable { | 701 | Runnable { |
510 | range: 1..80, | 702 | nav: NavigationTarget { |
703 | file_id: FileId( | ||
704 | 1, | ||
705 | ), | ||
706 | full_range: 1..80, | ||
707 | name: "test_foo1", | ||
708 | kind: FN_DEF, | ||
709 | focus_range: Some( | ||
710 | 66..75, | ||
711 | ), | ||
712 | container_name: None, | ||
713 | description: None, | ||
714 | docs: None, | ||
715 | }, | ||
511 | kind: Test { | 716 | kind: Test { |
512 | test_id: Path( | 717 | test_id: Path( |
513 | "test_foo1", | 718 | "test_foo1", |