diff --git a/crates/ra_ide_api/src/goto_definition.rs b/crates/ra_ide_api/src/goto_definition.rs index 40a2bd148d7c..163781f88ab3 100644 --- a/crates/ra_ide_api/src/goto_definition.rs +++ b/crates/ra_ide_api/src/goto_definition.rs @@ -25,6 +25,7 @@ pub(crate) fn goto_definition( None } +#[derive(Debug)] pub(crate) enum ReferenceResult { Exact(NavigationTarget), Approximate(Vec), diff --git a/crates/ra_ide_api/src/hover.rs b/crates/ra_ide_api/src/hover.rs index 397b567867a9..6545a25811f8 100644 --- a/crates/ra_ide_api/src/hover.rs +++ b/crates/ra_ide_api/src/hover.rs @@ -1,7 +1,7 @@ use ra_db::SourceDatabase; use ra_syntax::{ AstNode, ast, - algo::{find_covering_element, find_node_at_offset, find_token_at_offset}, + algo::{find_covering_element, find_node_at_offset, ancestors_at_offset}, }; use hir::HirDisplay; @@ -104,12 +104,8 @@ pub(crate) fn hover(db: &RootDatabase, position: FilePosition) -> Optionfoo; }; } +", + ); + let hover = analysis.hover(position).unwrap().unwrap(); + assert_eq!(trim_markup_opt(hover.info.first()), Some("i32")); + } + #[test] fn test_type_of_for_function() { let (analysis, range) = single_file_with_range( diff --git a/crates/ra_syntax/src/algo.rs b/crates/ra_syntax/src/algo.rs index 1f68fe467f55..d31d0034332b 100644 --- a/crates/ra_syntax/src/algo.rs +++ b/crates/ra_syntax/src/algo.rs @@ -1,5 +1,7 @@ pub mod visit; +use itertools::Itertools; + use crate::{SyntaxNode, TextRange, TextUnit, AstNode, Direction, SyntaxToken, SyntaxElement}; pub use rowan::TokenAtOffset; @@ -12,6 +14,20 @@ pub fn find_token_at_offset(node: &SyntaxNode, offset: TextUnit) -> TokenAtOffse } } +/// Returns ancestors of the node at the offset, sorted by length. This should +/// do the right thing at an edge, e.g. when searching for expressions at `{ +/// <|>foo }` we will get the name reference instead of the whole block, which +/// we would get if we just did `find_token_at_offset(...).flat_map(|t| +/// t.parent().ancestors())`. +pub fn ancestors_at_offset( + node: &SyntaxNode, + offset: TextUnit, +) -> impl Iterator { + find_token_at_offset(node, offset) + .map(|token| token.parent().ancestors()) + .kmerge_by(|node1, node2| node1.range().len() < node2.range().len()) +} + /// Finds a node of specific Ast type at offset. Note that this is slightly /// imprecise: if the cursor is strictly between two nodes of the desired type, /// as in @@ -20,10 +36,9 @@ pub fn find_token_at_offset(node: &SyntaxNode, offset: TextUnit) -> TokenAtOffse /// struct Foo {}|struct Bar; /// ``` /// -/// then the left node will be silently preferred. +/// then the shorter node will be silently preferred. pub fn find_node_at_offset(syntax: &SyntaxNode, offset: TextUnit) -> Option<&N> { - find_token_at_offset(syntax, offset) - .find_map(|leaf| leaf.parent().ancestors().find_map(N::cast)) + ancestors_at_offset(syntax, offset).find_map(N::cast) } /// Finds the first sibling in the given direction which is not `trivia`