From 7d0dd17b09240385333805637ea17992a8089cf2 Mon Sep 17 00:00:00 2001 From: vsrs Date: Wed, 3 Jun 2020 14:15:54 +0300 Subject: Add hover actions as LSP extension --- crates/ra_ide/src/hover.rs | 134 +++++++++++++++++++++++++++++++++++++++++---- crates/ra_ide/src/lib.rs | 2 +- 2 files changed, 123 insertions(+), 13 deletions(-) (limited to 'crates/ra_ide') diff --git a/crates/ra_ide/src/hover.rs b/crates/ra_ide/src/hover.rs index 9636cd0d6..baa9fc8a8 100644 --- a/crates/ra_ide/src/hover.rs +++ b/crates/ra_ide/src/hover.rs @@ -13,14 +13,43 @@ use ra_ide_db::{ use ra_syntax::{ast, match_ast, AstNode, SyntaxKind::*, SyntaxToken, TokenAtOffset}; use crate::{ - display::{macro_label, rust_code_markup, rust_code_markup_with_doc, ShortLabel}, - FilePosition, RangeInfo, + display::{macro_label, rust_code_markup, rust_code_markup_with_doc, ShortLabel, ToNav}, + FilePosition, RangeInfo, NavigationTarget, }; +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct HoverConfig { + pub implementations: bool, +} + +impl Default for HoverConfig { + fn default() -> Self { + Self { implementations: true } + } +} + +impl HoverConfig { + pub const NO_ACTIONS: Self = Self { implementations: false }; + + pub fn any(&self) -> bool { + self.implementations + } + + pub fn none(&self) -> bool { + !self.any() + } +} + +#[derive(Debug, Clone)] +pub enum HoverAction { + Implementaion(FilePosition), +} + /// Contains the results when hovering over an item #[derive(Debug, Default)] pub struct HoverResult { results: Vec, + actions: Vec, } impl HoverResult { @@ -48,10 +77,20 @@ impl HoverResult { &self.results } + pub fn actions(&self) -> &[HoverAction] { + &self.actions + } + + pub fn push_action(&mut self, action: HoverAction) { + self.actions.push(action); + } + /// Returns the results converted into markup /// for displaying in a UI + /// + /// Does not process actions! pub fn to_markup(&self) -> String { - self.results.join("\n\n---\n") + self.results.join("\n\n___\n") } } @@ -82,6 +121,10 @@ pub(crate) fn hover(db: &RootDatabase, position: FilePosition) -> Option Option Option { + fn to_action(nav_target: NavigationTarget) -> HoverAction { + HoverAction::Implementaion(FilePosition { + file_id: nav_target.file_id(), + offset: nav_target.range().start(), + }) + } + + match def { + Definition::ModuleDef(it) => match it { + ModuleDef::Adt(Adt::Struct(it)) => Some(to_action(it.to_nav(db))), + ModuleDef::Adt(Adt::Union(it)) => Some(to_action(it.to_nav(db))), + ModuleDef::Adt(Adt::Enum(it)) => Some(to_action(it.to_nav(db))), + ModuleDef::Trait(it) => Some(to_action(it.to_nav(db))), + _ => None, + }, + _ => None, + } +} + fn hover_text( docs: Option, desc: Option, @@ -228,6 +291,8 @@ fn pick_best(tokens: TokenAtOffset) -> Option { #[cfg(test)] mod tests { + use super::*; + use ra_db::FileLoader; use ra_syntax::TextRange; @@ -241,7 +306,14 @@ mod tests { s.map(trim_markup) } - fn check_hover_result(fixture: &str, expected: &[&str]) -> String { + fn assert_impl_action(action: &HoverAction, position: u32) { + let offset = match action { + HoverAction::Implementaion(pos) => pos.offset + }; + assert_eq!(offset, position.into()); + } + + fn check_hover_result(fixture: &str, expected: &[&str]) -> (String, Vec) { let (analysis, position) = analysis_and_position(fixture); let hover = analysis.hover(position).unwrap().unwrap(); let mut results = Vec::from(hover.info.results()); @@ -256,7 +328,7 @@ mod tests { assert_eq!(hover.info.len(), expected.len()); let content = analysis.db.file_text(position.file_id); - content[hover.range].to_string() + (content[hover.range].to_string(), hover.info.actions().to_vec()) } fn check_hover_no_result(fixture: &str) { @@ -746,7 +818,7 @@ fn func(foo: i32) { if true { <|>foo; }; } #[test] fn test_hover_through_macro() { - let hover_on = check_hover_result( + let (hover_on, _) = check_hover_result( " //- /lib.rs macro_rules! id { @@ -767,7 +839,7 @@ fn func(foo: i32) { if true { <|>foo; }; } #[test] fn test_hover_through_expr_in_macro() { - let hover_on = check_hover_result( + let (hover_on, _) = check_hover_result( " //- /lib.rs macro_rules! id { @@ -785,7 +857,7 @@ fn func(foo: i32) { if true { <|>foo; }; } #[test] fn test_hover_through_expr_in_macro_recursive() { - let hover_on = check_hover_result( + let (hover_on, _) = check_hover_result( " //- /lib.rs macro_rules! id_deep { @@ -806,7 +878,7 @@ fn func(foo: i32) { if true { <|>foo; }; } #[test] fn test_hover_through_func_in_macro_recursive() { - let hover_on = check_hover_result( + let (hover_on, _) = check_hover_result( " //- /lib.rs macro_rules! id_deep { @@ -830,7 +902,7 @@ fn func(foo: i32) { if true { <|>foo; }; } #[test] fn test_hover_through_literal_string_in_macro() { - let hover_on = check_hover_result( + let (hover_on, _) = check_hover_result( r#" //- /lib.rs macro_rules! arr { @@ -849,7 +921,7 @@ fn func(foo: i32) { if true { <|>foo; }; } #[test] fn test_hover_through_assert_macro() { - let hover_on = check_hover_result( + let (hover_on, _) = check_hover_result( r#" //- /lib.rs #[rustc_builtin_macro] @@ -925,13 +997,14 @@ fn func(foo: i32) { if true { <|>foo; }; } #[test] fn test_hover_trait_show_qualifiers() { - check_hover_result( + let (_, actions) = check_hover_result( " //- /lib.rs unsafe trait foo<|>() {} ", &["unsafe trait foo"], ); + assert_impl_action(&actions[0], 13); } #[test] @@ -1052,4 +1125,41 @@ fn func(foo: i32) { if true { <|>foo; }; } &["Bar\n```\n\n```rust\nfn foo(&self)\n```\n___\n\nDo the foo"], ); } + + #[test] + fn test_hover_trait_hash_impl_action() { + let (_, actions) = check_hover_result( + " + //- /lib.rs + trait foo<|>() {} + ", + &["trait foo"], + ); + assert_impl_action(&actions[0], 6); + } + + #[test] + fn test_hover_struct_hash_impl_action() { + let (_, actions) = check_hover_result( + " + //- /lib.rs + struct foo<|>() {} + ", + &["struct foo"], + ); + assert_impl_action(&actions[0], 7); + } + + #[test] + fn test_hover_union_hash_impl_action() { + let (_, actions) = check_hover_result( + " + //- /lib.rs + union foo<|>() {} + ", + &["union foo"], + ); + assert_impl_action(&actions[0], 6); + } + } diff --git a/crates/ra_ide/src/lib.rs b/crates/ra_ide/src/lib.rs index 34c2d75fe..a9601400f 100644 --- a/crates/ra_ide/src/lib.rs +++ b/crates/ra_ide/src/lib.rs @@ -66,7 +66,7 @@ pub use crate::{ display::{file_structure, FunctionSignature, NavigationTarget, StructureNode}, expand_macro::ExpandedMacro, folding_ranges::{Fold, FoldKind}, - hover::HoverResult, + hover::{HoverResult, HoverAction, HoverConfig}, inlay_hints::{InlayHint, InlayHintsConfig, InlayKind}, references::{Declaration, Reference, ReferenceAccess, ReferenceKind, ReferenceSearchResult}, runnables::{Runnable, RunnableKind, TestId}, -- cgit v1.2.3