From f615efdfc3b4655e4f74068769905404cd911b5e Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Tue, 22 Jun 2021 17:28:07 +0200 Subject: [PATCH] Factor out `pick_best_token` ide pattern into `ide_db` --- crates/ide/src/call_hierarchy.rs | 3 +-- crates/ide/src/doc_links.rs | 24 ++++++++-------------- crates/ide/src/expand_macro.rs | 22 ++++++-------------- crates/ide/src/goto_definition.rs | 23 ++++++++------------- crates/ide/src/goto_type_definition.rs | 21 ++++++++----------- crates/ide/src/hover.rs | 27 ++++++++----------------- crates/ide/src/lib.rs | 2 +- crates/ide/src/move_item.rs | 28 +++++++++----------------- crates/ide_db/src/helpers.rs | 13 +++++++++++- 9 files changed, 62 insertions(+), 101 deletions(-) diff --git a/crates/ide/src/call_hierarchy.rs b/crates/ide/src/call_hierarchy.rs index 5cd186565e..7bf35d2b36 100644 --- a/crates/ide/src/call_hierarchy.rs +++ b/crates/ide/src/call_hierarchy.rs @@ -3,8 +3,7 @@ use indexmap::IndexMap; use hir::Semantics; -use ide_db::call_info::FnCallNode; -use ide_db::RootDatabase; +use ide_db::{call_info::FnCallNode, RootDatabase}; use syntax::{ast, AstNode, TextRange}; use crate::{ diff --git a/crates/ide/src/doc_links.rs b/crates/ide/src/doc_links.rs index 7ac0118fe2..dfab8d313a 100644 --- a/crates/ide/src/doc_links.rs +++ b/crates/ide/src/doc_links.rs @@ -16,11 +16,10 @@ use hir::{ }; use ide_db::{ defs::{Definition, NameClass, NameRefClass}, + helpers::pick_best_token, RootDatabase, }; -use syntax::{ - ast, match_ast, AstNode, SyntaxKind::*, SyntaxNode, SyntaxToken, TextRange, TokenAtOffset, T, -}; +use syntax::{ast, match_ast, AstNode, SyntaxKind::*, SyntaxNode, TextRange, T}; use crate::{FilePosition, Semantics}; @@ -102,7 +101,12 @@ pub(crate) fn external_docs( ) -> Option { let sema = Semantics::new(db); let file = sema.parse(position.file_id).syntax().clone(); - let token = pick_best(file.token_at_offset(position.offset))?; + let token = pick_best_token(file.token_at_offset(position.offset), |kind| match kind { + IDENT | INT_NUMBER => 3, + T!['('] | T![')'] => 2, + kind if kind.is_trivia() => 0, + _ => 1, + })?; let token = sema.descend_into_macros(token); let node = token.parent()?; @@ -522,18 +526,6 @@ fn get_symbol_fragment(db: &dyn HirDatabase, field_or_assoc: &FieldOrAssocItem) }) } -fn pick_best(tokens: TokenAtOffset) -> Option { - return tokens.max_by_key(priority); - fn priority(n: &SyntaxToken) -> usize { - match n.kind() { - IDENT | INT_NUMBER => 3, - T!['('] | T![')'] => 2, - kind if kind.is_trivia() => 0, - _ => 1, - } - } -} - #[cfg(test)] mod tests { use expect_test::{expect, Expect}; diff --git a/crates/ide/src/expand_macro.rs b/crates/ide/src/expand_macro.rs index 12a091ac47..854d54b711 100644 --- a/crates/ide/src/expand_macro.rs +++ b/crates/ide/src/expand_macro.rs @@ -1,11 +1,8 @@ use std::iter; use hir::Semantics; -use ide_db::RootDatabase; -use syntax::{ - ast, ted, AstNode, NodeOrToken, SyntaxKind, SyntaxKind::*, SyntaxNode, SyntaxToken, - TokenAtOffset, WalkEvent, T, -}; +use ide_db::{helpers::pick_best_token, RootDatabase}; +use syntax::{ast, ted, AstNode, NodeOrToken, SyntaxKind, SyntaxKind::*, SyntaxNode, WalkEvent, T}; use crate::FilePosition; @@ -29,7 +26,10 @@ pub(crate) fn expand_macro(db: &RootDatabase, position: FilePosition) -> Option< let sema = Semantics::new(db); let file = sema.parse(position.file_id); - let tok = pick_best(file.syntax().token_at_offset(position.offset))?; + let tok = pick_best_token(file.syntax().token_at_offset(position.offset), |kind| match kind { + SyntaxKind::IDENT => 1, + _ => 0, + })?; let mut expanded = None; let mut name = None; for node in tok.ancestors() { @@ -57,16 +57,6 @@ pub(crate) fn expand_macro(db: &RootDatabase, position: FilePosition) -> Option< Some(ExpandedMacro { name: name?, expansion }) } -fn pick_best(tokens: TokenAtOffset) -> Option { - return tokens.max_by_key(priority); - fn priority(n: &SyntaxToken) -> usize { - match n.kind() { - IDENT => 1, - _ => 0, - } - } -} - fn expand_macro_recur( sema: &Semantics, macro_call: &ast::MacroCall, diff --git a/crates/ide/src/goto_definition.rs b/crates/ide/src/goto_definition.rs index d8e0dc4d59..df6c35780c 100644 --- a/crates/ide/src/goto_definition.rs +++ b/crates/ide/src/goto_definition.rs @@ -5,11 +5,10 @@ use hir::{AsAssocItem, InFile, ModuleDef, Semantics}; use ide_db::{ base_db::{AnchoredPath, FileId, FileLoader}, defs::{Definition, NameClass, NameRefClass}, + helpers::pick_best_token, RootDatabase, }; -use syntax::{ - ast, match_ast, AstNode, AstToken, SyntaxKind::*, SyntaxToken, TextRange, TokenAtOffset, T, -}; +use syntax::{ast, match_ast, AstNode, AstToken, SyntaxKind::*, SyntaxToken, TextRange, T}; use crate::{ display::TryToNav, @@ -34,7 +33,12 @@ pub(crate) fn goto_definition( ) -> Option>> { let sema = Semantics::new(db); let file = sema.parse(position.file_id).syntax().clone(); - let original_token = pick_best(file.token_at_offset(position.offset))?; + let original_token = + pick_best_token(file.token_at_offset(position.offset), |kind| match kind { + IDENT | INT_NUMBER | LIFETIME_IDENT | T![self] | COMMENT => 2, + kind if kind.is_trivia() => 0, + _ => 1, + })?; let token = sema.descend_into_macros(original_token.clone()); let parent = token.parent()?; if let Some(_) = ast::Comment::cast(token.clone()) { @@ -128,17 +132,6 @@ fn try_find_trait_item_definition(db: &RootDatabase, def: &Definition) -> Option .find_map(|itm| (itm.name(db)? == name).then(|| itm.try_to_nav(db)).flatten()) } -fn pick_best(tokens: TokenAtOffset) -> Option { - return tokens.max_by_key(priority); - fn priority(n: &SyntaxToken) -> usize { - match n.kind() { - IDENT | INT_NUMBER | LIFETIME_IDENT | T![self] | COMMENT => 2, - kind if kind.is_trivia() => 0, - _ => 1, - } - } -} - pub(crate) fn reference_definition( sema: &Semantics, name_ref: Either<&ast::Lifetime, &ast::NameRef>, diff --git a/crates/ide/src/goto_type_definition.rs b/crates/ide/src/goto_type_definition.rs index 43cffefe50..6263d3d4f0 100644 --- a/crates/ide/src/goto_type_definition.rs +++ b/crates/ide/src/goto_type_definition.rs @@ -1,6 +1,7 @@ use ide_db::base_db::Upcast; +use ide_db::helpers::pick_best_token; use ide_db::RootDatabase; -use syntax::{ast, match_ast, AstNode, SyntaxKind::*, SyntaxToken, TokenAtOffset, T}; +use syntax::{ast, match_ast, AstNode, SyntaxKind::*, SyntaxToken, T}; use crate::{display::TryToNav, FilePosition, NavigationTarget, RangeInfo}; @@ -22,7 +23,12 @@ pub(crate) fn goto_type_definition( let sema = hir::Semantics::new(db); let file: ast::SourceFile = sema.parse(position.file_id); - let token: SyntaxToken = pick_best(file.syntax().token_at_offset(position.offset))?; + let token: SyntaxToken = + pick_best_token(file.syntax().token_at_offset(position.offset), |kind| match kind { + IDENT | INT_NUMBER | T![self] => 2, + kind if kind.is_trivia() => 0, + _ => 1, + })?; let token: SyntaxToken = sema.descend_into_macros(token); let (ty, node) = sema.token_ancestors_with_macros(token).find_map(|node| { @@ -56,17 +62,6 @@ 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 | T![self] => 2, - kind if kind.is_trivia() => 0, - _ => 1, - } - } -} - #[cfg(test)] mod tests { use ide_db::base_db::FileRange; diff --git a/crates/ide/src/hover.rs b/crates/ide/src/hover.rs index c6d6bb74a8..0eeea4efb1 100644 --- a/crates/ide/src/hover.rs +++ b/crates/ide/src/hover.rs @@ -5,16 +5,13 @@ use ide_db::{ defs::{Definition, NameClass, NameRefClass}, helpers::{ generated_lints::{CLIPPY_LINTS, DEFAULT_LINTS, FEATURES}, - FamousDefs, + pick_best_token, FamousDefs, }, RootDatabase, }; use itertools::Itertools; use stdx::format_to; -use syntax::{ - algo, ast, match_ast, AstNode, AstToken, Direction, SyntaxKind::*, SyntaxToken, TokenAtOffset, - T, -}; +use syntax::{algo, ast, match_ast, AstNode, AstToken, Direction, SyntaxKind::*, SyntaxToken, T}; use crate::{ display::{macro_label, TryToNav}, @@ -80,7 +77,12 @@ pub(crate) fn hover( ) -> Option> { let sema = hir::Semantics::new(db); let file = sema.parse(position.file_id).syntax().clone(); - let token = pick_best(file.token_at_offset(position.offset))?; + let token = pick_best_token(file.token_at_offset(position.offset), |kind| match kind { + IDENT | INT_NUMBER | LIFETIME_IDENT | T![self] | T![super] | T![crate] => 3, + T!['('] | T![')'] => 2, + kind if kind.is_trivia() => 0, + _ => 1, + })?; let token = sema.descend_into_macros(token); let mut res = HoverResult::default(); @@ -519,19 +521,6 @@ fn find_std_module(famous_defs: &FamousDefs, name: &str) -> Option .find(|module| module.name(db).map_or(false, |module| module.to_string() == name)) } -fn pick_best(tokens: TokenAtOffset) -> Option { - return tokens.max_by_key(priority); - - fn priority(n: &SyntaxToken) -> usize { - match n.kind() { - IDENT | INT_NUMBER | LIFETIME_IDENT | T![self] | T![super] | T![crate] => 3, - T!['('] | T![')'] => 2, - kind if kind.is_trivia() => 0, - _ => 1, - } - } -} - #[cfg(test)] mod tests { use expect_test::{expect, Expect}; diff --git a/crates/ide/src/lib.rs b/crates/ide/src/lib.rs index b978e36af2..ca14533f38 100644 --- a/crates/ide/src/lib.rs +++ b/crates/ide/src/lib.rs @@ -439,7 +439,7 @@ impl Analysis { self.with_db(|db| call_hierarchy::incoming_calls(db, position)) } - /// Computes incoming calls for the given file position. + /// Computes outgoing calls for the given file position. pub fn outgoing_calls(&self, position: FilePosition) -> Cancellable>> { self.with_db(|db| call_hierarchy::outgoing_calls(db, position)) } diff --git a/crates/ide/src/move_item.rs b/crates/ide/src/move_item.rs index 246f10a0a8..1223c2810f 100644 --- a/crates/ide/src/move_item.rs +++ b/crates/ide/src/move_item.rs @@ -1,12 +1,9 @@ use std::{iter::once, mem}; use hir::Semantics; -use ide_db::{base_db::FileRange, RootDatabase}; +use ide_db::{base_db::FileRange, helpers::pick_best_token, RootDatabase}; use itertools::Itertools; -use syntax::{ - algo, ast, match_ast, AstNode, SyntaxElement, SyntaxKind, SyntaxNode, SyntaxToken, TextRange, - TokenAtOffset, -}; +use syntax::{algo, ast, match_ast, AstNode, SyntaxElement, SyntaxKind, SyntaxNode, TextRange}; use text_edit::{TextEdit, TextEditBuilder}; #[derive(Copy, Clone, Debug)] @@ -36,7 +33,14 @@ pub(crate) fn move_item( let file = sema.parse(range.file_id); let item = if range.range.is_empty() { - SyntaxElement::Token(pick_best(file.syntax().token_at_offset(range.range.start()))?) + SyntaxElement::Token(pick_best_token( + file.syntax().token_at_offset(range.range.start()), + |kind| match kind { + SyntaxKind::IDENT | SyntaxKind::LIFETIME_IDENT => 2, + kind if kind.is_trivia() => 0, + _ => 1, + }, + )?) } else { file.syntax().covering_element(range.range) }; @@ -170,18 +174,6 @@ fn replace_nodes<'a>( edit.finish() } -fn pick_best(tokens: TokenAtOffset) -> Option { - return tokens.max_by_key(priority); - - fn priority(n: &SyntaxToken) -> usize { - match n.kind() { - SyntaxKind::IDENT | SyntaxKind::LIFETIME_IDENT => 2, - kind if kind.is_trivia() => 0, - _ => 1, - } - } -} - #[cfg(test)] mod tests { use crate::fixture; diff --git a/crates/ide_db/src/helpers.rs b/crates/ide_db/src/helpers.rs index d96028cbcd..bc21977e36 100644 --- a/crates/ide_db/src/helpers.rs +++ b/crates/ide_db/src/helpers.rs @@ -10,7 +10,10 @@ use std::collections::VecDeque; use base_db::FileId; use either::Either; use hir::{Crate, Enum, ItemInNs, MacroDef, Module, ModuleDef, Name, ScopeDef, Semantics, Trait}; -use syntax::ast::{self, make}; +use syntax::{ + ast::{self, make}, + SyntaxKind, SyntaxToken, TokenAtOffset, +}; use crate::RootDatabase; @@ -22,6 +25,14 @@ pub fn item_name(db: &RootDatabase, item: ItemInNs) -> Option { } } +/// Picks the token with the highest rank returned by the passed in function. +pub fn pick_best_token( + tokens: TokenAtOffset, + f: impl Fn(SyntaxKind) -> usize, +) -> Option { + tokens.max_by_key(move |t| f(t.kind())) +} + /// Converts the mod path struct into its ast representation. pub fn mod_path_to_ast(path: &hir::ModPath) -> ast::Path { let _p = profile::span("mod_path_to_ast");