From 3434f1dd2c47fff3df159b9d62115c2df3fd6401 Mon Sep 17 00:00:00 2001 From: vsrs Date: Sat, 6 Jun 2020 14:30:29 +0300 Subject: Add Run|Debug hover actions --- crates/ra_ide/src/hover.rs | 129 +++++++++++++++++++++++++++++++++++++++-- crates/ra_ide/src/runnables.rs | 14 +++-- 2 files changed, 134 insertions(+), 9 deletions(-) (limited to 'crates/ra_ide/src') diff --git a/crates/ra_ide/src/hover.rs b/crates/ra_ide/src/hover.rs index 846d8c69b..138a7a7a9 100644 --- a/crates/ra_ide/src/hover.rs +++ b/crates/ra_ide/src/hover.rs @@ -14,34 +14,42 @@ use ra_syntax::{ast, match_ast, AstNode, SyntaxKind::*, SyntaxToken, TokenAtOffs use crate::{ display::{macro_label, rust_code_markup, rust_code_markup_with_doc, ShortLabel, ToNav}, - FilePosition, NavigationTarget, RangeInfo, + runnables::runnable, + FileId, FilePosition, NavigationTarget, RangeInfo, Runnable, }; #[derive(Clone, Debug, PartialEq, Eq)] pub struct HoverConfig { pub implementations: bool, + pub run: bool, + pub debug: bool, } impl Default for HoverConfig { fn default() -> Self { - Self { implementations: true } + Self { implementations: true, run: true, debug: true } } } impl HoverConfig { - pub const NO_ACTIONS: Self = Self { implementations: false }; + pub const NO_ACTIONS: Self = Self { implementations: false, run: false, debug: false }; pub fn any(&self) -> bool { - self.implementations + self.implementations || self.runnable() } pub fn none(&self) -> bool { !self.any() } + + pub fn runnable(&self) -> bool { + self.run || self.debug + } } #[derive(Debug, Clone)] pub enum HoverAction { + Runnable(Runnable), Implementaion(FilePosition), } @@ -125,6 +133,10 @@ pub(crate) fn hover(db: &RootDatabase, position: FilePosition) -> Option Option, + def: Definition, + file_id: FileId, +) -> Option { + match def { + Definition::ModuleDef(it) => match it { + ModuleDef::Module(it) => match it.definition_source(sema.db).value { + ModuleSource::Module(it) => runnable(&sema, it.syntax().clone(), file_id) + .map(|it| HoverAction::Runnable(it)), + _ => None, + }, + ModuleDef::Function(it) => { + runnable(&sema, it.source(sema.db).value.syntax().clone(), file_id) + .map(|it| HoverAction::Runnable(it)) + } + _ => None, + }, + _ => None, + } +} + fn hover_text( docs: Option, desc: Option, @@ -292,6 +326,7 @@ fn pick_best(tokens: TokenAtOffset) -> Option { #[cfg(test)] mod tests { use super::*; + use insta::assert_debug_snapshot; use ra_db::FileLoader; use ra_syntax::TextRange; @@ -309,6 +344,7 @@ mod tests { fn assert_impl_action(action: &HoverAction, position: u32) { let offset = match action { HoverAction::Implementaion(pos) => pos.offset, + it => panic!("Unexpected hover action: {:#?}", it), }; assert_eq!(offset, position.into()); } @@ -1176,4 +1212,89 @@ fn func(foo: i32) { if true { <|>foo; }; } ); assert_impl_action(&actions[0], 5); } + + #[test] + fn test_hover_test_has_action() { + let (_, actions) = check_hover_result( + " + //- /lib.rs + #[test] + fn foo_<|>test() {} + ", + &["fn foo_test()"], + ); + assert_debug_snapshot!(actions, + @r###" + [ + Runnable( + Runnable { + nav: NavigationTarget { + file_id: FileId( + 1, + ), + full_range: 0..24, + name: "foo_test", + kind: FN_DEF, + focus_range: Some( + 11..19, + ), + container_name: None, + description: None, + docs: None, + }, + kind: Test { + test_id: Path( + "foo_test", + ), + attr: TestAttr { + ignore: false, + }, + }, + cfg_exprs: [], + }, + ), + ] + "###); + } + + #[test] + fn test_hover_test_mod_has_action() { + let (_, actions) = check_hover_result( + " + //- /lib.rs + mod tests<|> { + #[test] + fn foo_test() {} + } + ", + &["mod tests"], + ); + assert_debug_snapshot!(actions, + @r###" + [ + Runnable( + Runnable { + nav: NavigationTarget { + file_id: FileId( + 1, + ), + full_range: 0..46, + name: "tests", + kind: MODULE, + focus_range: Some( + 4..9, + ), + container_name: None, + description: None, + docs: None, + }, + kind: TestMod { + path: "tests", + }, + cfg_exprs: [], + }, + ), + ] + "###); + } } diff --git a/crates/ra_ide/src/runnables.rs b/crates/ra_ide/src/runnables.rs index 9f7b5edfd..fc57dc33d 100644 --- a/crates/ra_ide/src/runnables.rs +++ b/crates/ra_ide/src/runnables.rs @@ -11,14 +11,14 @@ use ra_syntax::{ use crate::{display::ToNav, FileId, NavigationTarget}; -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct Runnable { pub nav: NavigationTarget, pub kind: RunnableKind, pub cfg_exprs: Vec, } -#[derive(Debug)] +#[derive(Debug, Clone)] pub enum TestId { Name(String), Path(String), @@ -33,7 +33,7 @@ impl fmt::Display for TestId { } } -#[derive(Debug)] +#[derive(Debug, Clone)] pub enum RunnableKind { Test { test_id: TestId, attr: TestAttr }, TestMod { path: String }, @@ -95,7 +95,11 @@ pub(crate) fn runnables(db: &RootDatabase, file_id: FileId) -> Vec { source_file.syntax().descendants().filter_map(|i| runnable(&sema, i, file_id)).collect() } -fn runnable(sema: &Semantics, item: SyntaxNode, file_id: FileId) -> Option { +pub(crate) fn runnable( + sema: &Semantics, + item: SyntaxNode, + file_id: FileId, +) -> Option { match_ast! { match item { ast::FnDef(it) => runnable_fn(sema, it, file_id), @@ -171,7 +175,7 @@ fn runnable_fn( Some(Runnable { nav, kind, cfg_exprs }) } -#[derive(Debug)] +#[derive(Debug, Copy, Clone)] pub struct TestAttr { pub ignore: bool, } -- cgit v1.2.3