Skip to content

Commit

Permalink
Merge #4773
Browse files Browse the repository at this point in the history
4773: Run|Debug hover actions. r=matklad a=vsrs

![hover_actions_run](https://user-images.githubusercontent.com/62505555/83335644-dfc1f780-a2b6-11ea-820b-ccaa82290e7d.gif)

This hover actions work exactly like corresponding lenses.

Co-authored-by: vsrs <[email protected]>
  • Loading branch information
bors[bot] and vsrs authored Jun 8, 2020
2 parents a5f427c + b7db9f0 commit 6e4fca5
Show file tree
Hide file tree
Showing 6 changed files with 312 additions and 68 deletions.
142 changes: 138 additions & 4 deletions crates/ra_ide/src/hover.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,34 +14,43 @@ 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,
};
use test_utils::mark;

#[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),
}

Expand Down Expand Up @@ -125,6 +134,10 @@ pub(crate) fn hover(db: &RootDatabase, position: FilePosition) -> Option<RangeIn
res.push_action(action);
}

if let Some(action) = runnable_action(&sema, name_kind, position.file_id) {
res.push_action(action);
}

return Some(RangeInfo::new(range, res));
}
}
Expand Down Expand Up @@ -175,6 +188,36 @@ fn show_implementations_action(db: &RootDatabase, def: Definition) -> Option<Hov
}
}

fn runnable_action(
sema: &Semantics<RootDatabase>,
def: Definition,
file_id: FileId,
) -> Option<HoverAction> {
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) => {
let src = it.source(sema.db);
if src.file_id != file_id.into() {
mark::hit!(hover_macro_generated_struct_fn_doc_comment);
mark::hit!(hover_macro_generated_struct_fn_doc_attr);

return None;
}

runnable(&sema, src.value.syntax().clone(), file_id)
.map(|it| HoverAction::Runnable(it))
}
_ => None,
},
_ => None,
}
}

fn hover_text(
docs: Option<String>,
desc: Option<String>,
Expand Down Expand Up @@ -292,6 +335,7 @@ fn pick_best(tokens: TokenAtOffset<SyntaxToken>) -> Option<SyntaxToken> {
#[cfg(test)]
mod tests {
use super::*;
use insta::assert_debug_snapshot;

use ra_db::FileLoader;
use ra_syntax::TextRange;
Expand All @@ -309,6 +353,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());
}
Expand Down Expand Up @@ -1076,6 +1121,8 @@ fn func(foo: i32) { if true { <|>foo; }; }

#[test]
fn test_hover_macro_generated_struct_fn_doc_comment() {
mark::check!(hover_macro_generated_struct_fn_doc_comment);

check_hover_result(
r#"
//- /lib.rs
Expand All @@ -1102,6 +1149,8 @@ fn func(foo: i32) { if true { <|>foo; }; }

#[test]
fn test_hover_macro_generated_struct_fn_doc_attr() {
mark::check!(hover_macro_generated_struct_fn_doc_attr);

check_hover_result(
r#"
//- /lib.rs
Expand Down Expand Up @@ -1176,4 +1225,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: [],
},
),
]
"###);
}
}
Loading

0 comments on commit 6e4fca5

Please sign in to comment.