From 4df741ecb2d00c3d8cdbc37d734ff5514dd5e7b0 Mon Sep 17 00:00:00 2001 From: succcubbus <16743652+succcubbus@users.noreply.github.com> Date: Fri, 13 Dec 2019 19:20:02 +0100 Subject: fix goto definition when inbetween tokens fixes both goto_definition and goto_type_definition. before, when running goto between some non-trivia token and an identifier, goto would be attempted for the non-trivia token. but this does not make sense for e.g. L_PAREN or COLONCOLON only for IDENTs. now only IDENTs will be searched for in goto actions. --- crates/ra_ide/src/goto_definition.rs | 16 ++++++++++++++-- crates/ra_ide/src/goto_type_definition.rs | 16 ++++++++++++++-- 2 files changed, 28 insertions(+), 4 deletions(-) diff --git a/crates/ra_ide/src/goto_definition.rs b/crates/ra_ide/src/goto_definition.rs index cfe62037f..96a73675f 100644 --- a/crates/ra_ide/src/goto_definition.rs +++ b/crates/ra_ide/src/goto_definition.rs @@ -3,7 +3,7 @@ use hir::{db::AstDatabase, InFile}; use ra_syntax::{ ast::{self, DocCommentsOwner}, - match_ast, AstNode, SyntaxNode, + match_ast, AstNode, SyntaxKind, SyntaxNode, }; use crate::{ @@ -20,7 +20,7 @@ pub(crate) fn goto_definition( ) -> Option>> { let file = db.parse_or_expand(position.file_id.into())?; let original_token = - file.token_at_offset(position.offset).filter(|it| !it.kind().is_trivia()).next()?; + file.token_at_offset(position.offset).find(|it| it.kind() == SyntaxKind::IDENT)?; let token = descend_into_macros(db, position.file_id, original_token.clone()); let nav_targets = match_ast! { @@ -234,6 +234,18 @@ mod tests { ); } + #[test] + fn goto_definition_works_at_start_of_item() { + check_goto( + " + //- /lib.rs + struct Foo; + enum E { X(<|>Foo) } + ", + "Foo STRUCT_DEF FileId(1) [0; 11) [7; 10)", + ); + } + #[test] fn goto_definition_resolves_correct_name() { check_goto( diff --git a/crates/ra_ide/src/goto_type_definition.rs b/crates/ra_ide/src/goto_type_definition.rs index 992a08809..cc1b90925 100644 --- a/crates/ra_ide/src/goto_type_definition.rs +++ b/crates/ra_ide/src/goto_type_definition.rs @@ -1,7 +1,7 @@ //! FIXME: write short doc here use hir::db::AstDatabase; -use ra_syntax::{ast, AstNode}; +use ra_syntax::{ast, AstNode, SyntaxKind}; use crate::{ db::RootDatabase, display::ToNav, expand::descend_into_macros, FilePosition, NavigationTarget, @@ -13,7 +13,7 @@ pub(crate) fn goto_type_definition( position: FilePosition, ) -> Option>> { let file = db.parse_or_expand(position.file_id.into())?; - let token = file.token_at_offset(position.offset).filter(|it| !it.kind().is_trivia()).next()?; + let token = file.token_at_offset(position.offset).find(|it| it.kind() == SyntaxKind::IDENT)?; let token = descend_into_macros(db, position.file_id, token); let node = token.value.ancestors().find_map(|token| { @@ -102,4 +102,16 @@ mod tests { "Foo STRUCT_DEF FileId(1) [52; 65) [59; 62)", ); } + + #[test] + fn goto_type_definition_works_param() { + check_goto( + " + //- /lib.rs + struct Foo; + fn foo(<|>f: Foo) {} + ", + "Foo STRUCT_DEF FileId(1) [0; 11) [7; 10)", + ); + } } -- cgit v1.2.3 From f54fef85aa88db44b1d3f6436551595dcb98ab83 Mon Sep 17 00:00:00 2001 From: succcubbus <16743652+succcubbus@users.noreply.github.com> Date: Fri, 13 Dec 2019 19:54:02 +0100 Subject: use find() instead of filter().next() --- crates/ra_ide/src/hover.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/ra_ide/src/hover.rs b/crates/ra_ide/src/hover.rs index d372ca758..24f7eeed3 100644 --- a/crates/ra_ide/src/hover.rs +++ b/crates/ra_ide/src/hover.rs @@ -156,7 +156,7 @@ fn hover_text_from_name_kind( pub(crate) fn hover(db: &RootDatabase, position: FilePosition) -> Option> { let file = db.parse_or_expand(position.file_id.into())?; - let token = file.token_at_offset(position.offset).filter(|it| !it.kind().is_trivia()).next()?; + let token = file.token_at_offset(position.offset).find(|it| !it.kind().is_trivia())?; let token = descend_into_macros(db, position.file_id, token); let mut res = HoverResult::new(); -- cgit v1.2.3 From 6c42eb1930f179bca1867eebcbf82c7bc10dd4c5 Mon Sep 17 00:00:00 2001 From: succcubbus <16743652+succcubbus@users.noreply.github.com> Date: Fri, 13 Dec 2019 19:54:07 +0100 Subject: add failing test --- crates/ra_ide/src/hover.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/crates/ra_ide/src/hover.rs b/crates/ra_ide/src/hover.rs index 24f7eeed3..b2909bf38 100644 --- a/crates/ra_ide/src/hover.rs +++ b/crates/ra_ide/src/hover.rs @@ -504,6 +504,13 @@ fn func(foo: i32) { if true { <|>foo; }; } assert_eq!(trim_markup_opt(hover.info.first()), Some("i32")); } + #[test] + fn hover_for_param_edge() { + let (analysis, position) = single_file_with_position("fn func(<|>foo: i32) {}"); + 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( -- cgit v1.2.3 From 6c133017a80c41db361d7870bf57db3e43c4074a Mon Sep 17 00:00:00 2001 From: succcubbus <16743652+succcubbus@users.noreply.github.com> Date: Fri, 13 Dec 2019 21:10:25 +0100 Subject: try both surrounding tokens for hover --- crates/ra_ide/src/hover.rs | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/crates/ra_ide/src/hover.rs b/crates/ra_ide/src/hover.rs index b2909bf38..5b48b1998 100644 --- a/crates/ra_ide/src/hover.rs +++ b/crates/ra_ide/src/hover.rs @@ -1,11 +1,11 @@ //! FIXME: write short doc here -use hir::{db::AstDatabase, Adt, HasSource, HirDisplay}; +use hir::{db::AstDatabase, Adt, HasSource, HirDisplay, InFile}; use ra_db::SourceDatabase; use ra_syntax::{ algo::find_covering_element, ast::{self, DocCommentsOwner}, - match_ast, AstNode, + match_ast, AstNode, SyntaxToken, }; use crate::{ @@ -156,9 +156,17 @@ fn hover_text_from_name_kind( pub(crate) fn hover(db: &RootDatabase, position: FilePosition) -> Option> { let file = db.parse_or_expand(position.file_id.into())?; - let token = file.token_at_offset(position.offset).find(|it| !it.kind().is_trivia())?; - let token = descend_into_macros(db, position.file_id, token); + file.token_at_offset(position.offset) + .filter(|token| !token.kind().is_trivia()) + .map(|token| descend_into_macros(db, position.file_id, token)) + .find_map(|token| hover_token(db, position, token)) +} +fn hover_token( + db: &RootDatabase, + position: FilePosition, + token: InFile, +) -> Option> { let mut res = HoverResult::new(); let mut range = match_ast! { -- cgit v1.2.3 From 4f7da04c6735e1d00fceb6fc6f83542626ce03c9 Mon Sep 17 00:00:00 2001 From: succcubbus <16743652+succcubbus@users.noreply.github.com> Date: Fri, 13 Dec 2019 21:59:25 +0100 Subject: add tests for goto on tuple fields --- crates/ra_ide/src/goto_definition.rs | 16 ++++++++++++++++ crates/ra_ide/src/goto_type_definition.rs | 18 +++++++++++++++++- 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/crates/ra_ide/src/goto_definition.rs b/crates/ra_ide/src/goto_definition.rs index 96a73675f..30118b43f 100644 --- a/crates/ra_ide/src/goto_definition.rs +++ b/crates/ra_ide/src/goto_definition.rs @@ -446,6 +446,22 @@ mod tests { ); } + #[test] + fn goto_for_tuple_fields() { + check_goto( + " + //- /lib.rs + struct Foo(u32); + + fn bar() { + let foo = Foo(0); + foo.<|>0; + } + ", + "TUPLE_FIELD_DEF FileId(1) [11; 14)", + ); + } + #[test] fn goto_definition_works_for_ufcs_inherent_methods() { check_goto( diff --git a/crates/ra_ide/src/goto_type_definition.rs b/crates/ra_ide/src/goto_type_definition.rs index cc1b90925..5501bb742 100644 --- a/crates/ra_ide/src/goto_type_definition.rs +++ b/crates/ra_ide/src/goto_type_definition.rs @@ -104,7 +104,7 @@ mod tests { } #[test] - fn goto_type_definition_works_param() { + fn goto_type_definition_for_param() { check_goto( " //- /lib.rs @@ -114,4 +114,20 @@ mod tests { "Foo STRUCT_DEF FileId(1) [0; 11) [7; 10)", ); } + + #[test] + fn goto_type_definition_for_tuple_field() { + check_goto( + " + //- /lib.rs + struct Foo; + struct Bar(Foo); + fn foo() { + let bar = Bar(Foo); + bar.<|>0; + } + ", + "Foo STRUCT_DEF FileId(1) [0; 11) [7; 10)", + ); + } } -- cgit v1.2.3 From c82529a97f10b1302d2944f1946bcb3479f64e2d Mon Sep 17 00:00:00 2001 From: succcubbus <16743652+succcubbus@users.noreply.github.com> Date: Fri, 13 Dec 2019 22:00:05 +0100 Subject: for goto and hover pick the token based on a priority --- crates/ra_ide/src/goto_definition.rs | 18 +++++++++++++++--- crates/ra_ide/src/goto_type_definition.rs | 15 +++++++++++++-- crates/ra_ide/src/hover.rs | 30 ++++++++++++++++++------------ 3 files changed, 46 insertions(+), 17 deletions(-) diff --git a/crates/ra_ide/src/goto_definition.rs b/crates/ra_ide/src/goto_definition.rs index 30118b43f..27052d72b 100644 --- a/crates/ra_ide/src/goto_definition.rs +++ b/crates/ra_ide/src/goto_definition.rs @@ -3,7 +3,9 @@ use hir::{db::AstDatabase, InFile}; use ra_syntax::{ ast::{self, DocCommentsOwner}, - match_ast, AstNode, SyntaxKind, SyntaxNode, + match_ast, AstNode, + SyntaxKind::*, + SyntaxNode, SyntaxToken, TokenAtOffset, }; use crate::{ @@ -19,8 +21,7 @@ pub(crate) fn goto_definition( position: FilePosition, ) -> Option>> { let file = db.parse_or_expand(position.file_id.into())?; - let original_token = - file.token_at_offset(position.offset).find(|it| it.kind() == SyntaxKind::IDENT)?; + let original_token = pick_best(file.token_at_offset(position.offset))?; let token = descend_into_macros(db, position.file_id, original_token.clone()); let nav_targets = match_ast! { @@ -38,6 +39,17 @@ pub(crate) fn goto_definition( Some(RangeInfo::new(original_token.text_range(), nav_targets)) } +fn pick_best(tokens: TokenAtOffset) -> Option { + return tokens.max_by_key(priority); + fn priority(n: &SyntaxToken) -> usize { + match n.kind() { + IDENT | INT_NUMBER => 2, + kind if kind.is_trivia() => 0, + _ => 1, + } + } +} + #[derive(Debug)] pub(crate) enum ReferenceResult { Exact(NavigationTarget), diff --git a/crates/ra_ide/src/goto_type_definition.rs b/crates/ra_ide/src/goto_type_definition.rs index 5501bb742..ce8b6c72a 100644 --- a/crates/ra_ide/src/goto_type_definition.rs +++ b/crates/ra_ide/src/goto_type_definition.rs @@ -1,7 +1,7 @@ //! FIXME: write short doc here use hir::db::AstDatabase; -use ra_syntax::{ast, AstNode, SyntaxKind}; +use ra_syntax::{ast, AstNode, SyntaxKind::*, SyntaxToken, TokenAtOffset}; use crate::{ db::RootDatabase, display::ToNav, expand::descend_into_macros, FilePosition, NavigationTarget, @@ -13,7 +13,7 @@ pub(crate) fn goto_type_definition( position: FilePosition, ) -> Option>> { let file = db.parse_or_expand(position.file_id.into())?; - let token = file.token_at_offset(position.offset).find(|it| it.kind() == SyntaxKind::IDENT)?; + let token = pick_best(file.token_at_offset(position.offset))?; let token = descend_into_macros(db, position.file_id, token); let node = token.value.ancestors().find_map(|token| { @@ -41,6 +41,17 @@ pub(crate) fn goto_type_definition( Some(RangeInfo::new(node.text_range(), vec![nav])) } +fn pick_best(tokens: TokenAtOffset) -> Option { + return tokens.max_by_key(priority); + fn priority(n: &SyntaxToken) -> usize { + match n.kind() { + IDENT | INT_NUMBER => 2, + kind if kind.is_trivia() => 0, + _ => 1, + } + } +} + #[cfg(test)] mod tests { use crate::mock_analysis::analysis_and_position; diff --git a/crates/ra_ide/src/hover.rs b/crates/ra_ide/src/hover.rs index 5b48b1998..51e320128 100644 --- a/crates/ra_ide/src/hover.rs +++ b/crates/ra_ide/src/hover.rs @@ -1,11 +1,13 @@ //! FIXME: write short doc here -use hir::{db::AstDatabase, Adt, HasSource, HirDisplay, InFile}; +use hir::{db::AstDatabase, Adt, HasSource, HirDisplay}; use ra_db::SourceDatabase; use ra_syntax::{ algo::find_covering_element, ast::{self, DocCommentsOwner}, - match_ast, AstNode, SyntaxToken, + match_ast, AstNode, + SyntaxKind::*, + SyntaxToken, TokenAtOffset, }; use crate::{ @@ -156,17 +158,9 @@ fn hover_text_from_name_kind( pub(crate) fn hover(db: &RootDatabase, position: FilePosition) -> Option> { let file = db.parse_or_expand(position.file_id.into())?; - file.token_at_offset(position.offset) - .filter(|token| !token.kind().is_trivia()) - .map(|token| descend_into_macros(db, position.file_id, token)) - .find_map(|token| hover_token(db, position, token)) -} + let token = pick_best(file.token_at_offset(position.offset))?; + let token = descend_into_macros(db, position.file_id, token); -fn hover_token( - db: &RootDatabase, - position: FilePosition, - token: InFile, -) -> Option> { let mut res = HoverResult::new(); let mut range = match_ast! { @@ -226,6 +220,18 @@ fn hover_token( Some(RangeInfo::new(range, res)) } +fn pick_best(tokens: TokenAtOffset) -> Option { + return tokens.max_by_key(priority); + fn priority(n: &SyntaxToken) -> usize { + match n.kind() { + IDENT | INT_NUMBER => 3, + L_PAREN | R_PAREN => 2, + kind if kind.is_trivia() => 0, + _ => 1, + } + } +} + pub(crate) fn type_of(db: &RootDatabase, frange: FileRange) -> Option { let parse = db.parse(frange.file_id); let leaf_node = find_covering_element(parse.tree().syntax(), frange.range); -- cgit v1.2.3