diff options
author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2021-06-22 18:17:54 +0100 |
---|---|---|
committer | GitHub <[email protected]> | 2021-06-22 18:17:54 +0100 |
commit | 76c88e9ca9ea9000d7d9eda1b2dae3173296f738 (patch) | |
tree | 8e7d42ad63269c668b189c0a59d55ebd53328f90 | |
parent | 4e2ec914f4b9609d162c3fd1776e8d293428fe5a (diff) | |
parent | f615efdfc3b4655e4f74068769905404cd911b5e (diff) |
Merge #9373
9373: internal: Factor out `pick_best_token` ide pattern into `ide_db` r=Veykril a=Veykril
bors r+
Co-authored-by: Lukas Wirth <[email protected]>
-rw-r--r-- | crates/ide/src/call_hierarchy.rs | 3 | ||||
-rw-r--r-- | crates/ide/src/doc_links.rs | 24 | ||||
-rw-r--r-- | crates/ide/src/expand_macro.rs | 22 | ||||
-rw-r--r-- | crates/ide/src/goto_definition.rs | 23 | ||||
-rw-r--r-- | crates/ide/src/goto_type_definition.rs | 21 | ||||
-rw-r--r-- | crates/ide/src/hover.rs | 27 | ||||
-rw-r--r-- | crates/ide/src/lib.rs | 2 | ||||
-rw-r--r-- | crates/ide/src/move_item.rs | 28 | ||||
-rw-r--r-- | 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 5cd186565..7bf35d2b3 100644 --- a/crates/ide/src/call_hierarchy.rs +++ b/crates/ide/src/call_hierarchy.rs | |||
@@ -3,8 +3,7 @@ | |||
3 | use indexmap::IndexMap; | 3 | use indexmap::IndexMap; |
4 | 4 | ||
5 | use hir::Semantics; | 5 | use hir::Semantics; |
6 | use ide_db::call_info::FnCallNode; | 6 | use ide_db::{call_info::FnCallNode, RootDatabase}; |
7 | use ide_db::RootDatabase; | ||
8 | use syntax::{ast, AstNode, TextRange}; | 7 | use syntax::{ast, AstNode, TextRange}; |
9 | 8 | ||
10 | use crate::{ | 9 | use crate::{ |
diff --git a/crates/ide/src/doc_links.rs b/crates/ide/src/doc_links.rs index 7ac0118fe..dfab8d313 100644 --- a/crates/ide/src/doc_links.rs +++ b/crates/ide/src/doc_links.rs | |||
@@ -16,11 +16,10 @@ use hir::{ | |||
16 | }; | 16 | }; |
17 | use ide_db::{ | 17 | use ide_db::{ |
18 | defs::{Definition, NameClass, NameRefClass}, | 18 | defs::{Definition, NameClass, NameRefClass}, |
19 | helpers::pick_best_token, | ||
19 | RootDatabase, | 20 | RootDatabase, |
20 | }; | 21 | }; |
21 | use syntax::{ | 22 | use syntax::{ast, match_ast, AstNode, SyntaxKind::*, SyntaxNode, TextRange, T}; |
22 | ast, match_ast, AstNode, SyntaxKind::*, SyntaxNode, SyntaxToken, TextRange, TokenAtOffset, T, | ||
23 | }; | ||
24 | 23 | ||
25 | use crate::{FilePosition, Semantics}; | 24 | use crate::{FilePosition, Semantics}; |
26 | 25 | ||
@@ -102,7 +101,12 @@ pub(crate) fn external_docs( | |||
102 | ) -> Option<DocumentationLink> { | 101 | ) -> Option<DocumentationLink> { |
103 | let sema = Semantics::new(db); | 102 | let sema = Semantics::new(db); |
104 | let file = sema.parse(position.file_id).syntax().clone(); | 103 | let file = sema.parse(position.file_id).syntax().clone(); |
105 | let token = pick_best(file.token_at_offset(position.offset))?; | 104 | let token = pick_best_token(file.token_at_offset(position.offset), |kind| match kind { |
105 | IDENT | INT_NUMBER => 3, | ||
106 | T!['('] | T![')'] => 2, | ||
107 | kind if kind.is_trivia() => 0, | ||
108 | _ => 1, | ||
109 | })?; | ||
106 | let token = sema.descend_into_macros(token); | 110 | let token = sema.descend_into_macros(token); |
107 | 111 | ||
108 | let node = token.parent()?; | 112 | let node = token.parent()?; |
@@ -522,18 +526,6 @@ fn get_symbol_fragment(db: &dyn HirDatabase, field_or_assoc: &FieldOrAssocItem) | |||
522 | }) | 526 | }) |
523 | } | 527 | } |
524 | 528 | ||
525 | fn pick_best(tokens: TokenAtOffset<SyntaxToken>) -> Option<SyntaxToken> { | ||
526 | return tokens.max_by_key(priority); | ||
527 | fn priority(n: &SyntaxToken) -> usize { | ||
528 | match n.kind() { | ||
529 | IDENT | INT_NUMBER => 3, | ||
530 | T!['('] | T![')'] => 2, | ||
531 | kind if kind.is_trivia() => 0, | ||
532 | _ => 1, | ||
533 | } | ||
534 | } | ||
535 | } | ||
536 | |||
537 | #[cfg(test)] | 529 | #[cfg(test)] |
538 | mod tests { | 530 | mod tests { |
539 | use expect_test::{expect, Expect}; | 531 | use expect_test::{expect, Expect}; |
diff --git a/crates/ide/src/expand_macro.rs b/crates/ide/src/expand_macro.rs index 12a091ac4..854d54b71 100644 --- a/crates/ide/src/expand_macro.rs +++ b/crates/ide/src/expand_macro.rs | |||
@@ -1,11 +1,8 @@ | |||
1 | use std::iter; | 1 | use std::iter; |
2 | 2 | ||
3 | use hir::Semantics; | 3 | use hir::Semantics; |
4 | use ide_db::RootDatabase; | 4 | use ide_db::{helpers::pick_best_token, RootDatabase}; |
5 | use syntax::{ | 5 | use syntax::{ast, ted, AstNode, NodeOrToken, SyntaxKind, SyntaxKind::*, SyntaxNode, WalkEvent, T}; |
6 | ast, ted, AstNode, NodeOrToken, SyntaxKind, SyntaxKind::*, SyntaxNode, SyntaxToken, | ||
7 | TokenAtOffset, WalkEvent, T, | ||
8 | }; | ||
9 | 6 | ||
10 | use crate::FilePosition; | 7 | use crate::FilePosition; |
11 | 8 | ||
@@ -29,7 +26,10 @@ pub(crate) fn expand_macro(db: &RootDatabase, position: FilePosition) -> Option< | |||
29 | let sema = Semantics::new(db); | 26 | let sema = Semantics::new(db); |
30 | let file = sema.parse(position.file_id); | 27 | let file = sema.parse(position.file_id); |
31 | 28 | ||
32 | let tok = pick_best(file.syntax().token_at_offset(position.offset))?; | 29 | let tok = pick_best_token(file.syntax().token_at_offset(position.offset), |kind| match kind { |
30 | SyntaxKind::IDENT => 1, | ||
31 | _ => 0, | ||
32 | })?; | ||
33 | let mut expanded = None; | 33 | let mut expanded = None; |
34 | let mut name = None; | 34 | let mut name = None; |
35 | for node in tok.ancestors() { | 35 | for node in tok.ancestors() { |
@@ -57,16 +57,6 @@ pub(crate) fn expand_macro(db: &RootDatabase, position: FilePosition) -> Option< | |||
57 | Some(ExpandedMacro { name: name?, expansion }) | 57 | Some(ExpandedMacro { name: name?, expansion }) |
58 | } | 58 | } |
59 | 59 | ||
60 | fn pick_best(tokens: TokenAtOffset<SyntaxToken>) -> Option<SyntaxToken> { | ||
61 | return tokens.max_by_key(priority); | ||
62 | fn priority(n: &SyntaxToken) -> usize { | ||
63 | match n.kind() { | ||
64 | IDENT => 1, | ||
65 | _ => 0, | ||
66 | } | ||
67 | } | ||
68 | } | ||
69 | |||
70 | fn expand_macro_recur( | 60 | fn expand_macro_recur( |
71 | sema: &Semantics<RootDatabase>, | 61 | sema: &Semantics<RootDatabase>, |
72 | macro_call: &ast::MacroCall, | 62 | macro_call: &ast::MacroCall, |
diff --git a/crates/ide/src/goto_definition.rs b/crates/ide/src/goto_definition.rs index d8e0dc4d5..df6c35780 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}; | |||
5 | use ide_db::{ | 5 | use ide_db::{ |
6 | base_db::{AnchoredPath, FileId, FileLoader}, | 6 | base_db::{AnchoredPath, FileId, FileLoader}, |
7 | defs::{Definition, NameClass, NameRefClass}, | 7 | defs::{Definition, NameClass, NameRefClass}, |
8 | helpers::pick_best_token, | ||
8 | RootDatabase, | 9 | RootDatabase, |
9 | }; | 10 | }; |
10 | use syntax::{ | 11 | use syntax::{ast, match_ast, AstNode, AstToken, SyntaxKind::*, SyntaxToken, TextRange, T}; |
11 | ast, match_ast, AstNode, AstToken, SyntaxKind::*, SyntaxToken, TextRange, TokenAtOffset, T, | ||
12 | }; | ||
13 | 12 | ||
14 | use crate::{ | 13 | use crate::{ |
15 | display::TryToNav, | 14 | display::TryToNav, |
@@ -34,7 +33,12 @@ pub(crate) fn goto_definition( | |||
34 | ) -> Option<RangeInfo<Vec<NavigationTarget>>> { | 33 | ) -> Option<RangeInfo<Vec<NavigationTarget>>> { |
35 | let sema = Semantics::new(db); | 34 | let sema = Semantics::new(db); |
36 | let file = sema.parse(position.file_id).syntax().clone(); | 35 | let file = sema.parse(position.file_id).syntax().clone(); |
37 | let original_token = pick_best(file.token_at_offset(position.offset))?; | 36 | let original_token = |
37 | pick_best_token(file.token_at_offset(position.offset), |kind| match kind { | ||
38 | IDENT | INT_NUMBER | LIFETIME_IDENT | T![self] | COMMENT => 2, | ||
39 | kind if kind.is_trivia() => 0, | ||
40 | _ => 1, | ||
41 | })?; | ||
38 | let token = sema.descend_into_macros(original_token.clone()); | 42 | let token = sema.descend_into_macros(original_token.clone()); |
39 | let parent = token.parent()?; | 43 | let parent = token.parent()?; |
40 | if let Some(_) = ast::Comment::cast(token.clone()) { | 44 | if let Some(_) = ast::Comment::cast(token.clone()) { |
@@ -128,17 +132,6 @@ fn try_find_trait_item_definition(db: &RootDatabase, def: &Definition) -> Option | |||
128 | .find_map(|itm| (itm.name(db)? == name).then(|| itm.try_to_nav(db)).flatten()) | 132 | .find_map(|itm| (itm.name(db)? == name).then(|| itm.try_to_nav(db)).flatten()) |
129 | } | 133 | } |
130 | 134 | ||
131 | fn pick_best(tokens: TokenAtOffset<SyntaxToken>) -> Option<SyntaxToken> { | ||
132 | return tokens.max_by_key(priority); | ||
133 | fn priority(n: &SyntaxToken) -> usize { | ||
134 | match n.kind() { | ||
135 | IDENT | INT_NUMBER | LIFETIME_IDENT | T![self] | COMMENT => 2, | ||
136 | kind if kind.is_trivia() => 0, | ||
137 | _ => 1, | ||
138 | } | ||
139 | } | ||
140 | } | ||
141 | |||
142 | pub(crate) fn reference_definition( | 135 | pub(crate) fn reference_definition( |
143 | sema: &Semantics<RootDatabase>, | 136 | sema: &Semantics<RootDatabase>, |
144 | name_ref: Either<&ast::Lifetime, &ast::NameRef>, | 137 | 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 43cffefe5..6263d3d4f 100644 --- a/crates/ide/src/goto_type_definition.rs +++ b/crates/ide/src/goto_type_definition.rs | |||
@@ -1,6 +1,7 @@ | |||
1 | use ide_db::base_db::Upcast; | 1 | use ide_db::base_db::Upcast; |
2 | use ide_db::helpers::pick_best_token; | ||
2 | use ide_db::RootDatabase; | 3 | use ide_db::RootDatabase; |
3 | use syntax::{ast, match_ast, AstNode, SyntaxKind::*, SyntaxToken, TokenAtOffset, T}; | 4 | use syntax::{ast, match_ast, AstNode, SyntaxKind::*, SyntaxToken, T}; |
4 | 5 | ||
5 | use crate::{display::TryToNav, FilePosition, NavigationTarget, RangeInfo}; | 6 | use crate::{display::TryToNav, FilePosition, NavigationTarget, RangeInfo}; |
6 | 7 | ||
@@ -22,7 +23,12 @@ pub(crate) fn goto_type_definition( | |||
22 | let sema = hir::Semantics::new(db); | 23 | let sema = hir::Semantics::new(db); |
23 | 24 | ||
24 | let file: ast::SourceFile = sema.parse(position.file_id); | 25 | let file: ast::SourceFile = sema.parse(position.file_id); |
25 | let token: SyntaxToken = pick_best(file.syntax().token_at_offset(position.offset))?; | 26 | let token: SyntaxToken = |
27 | pick_best_token(file.syntax().token_at_offset(position.offset), |kind| match kind { | ||
28 | IDENT | INT_NUMBER | T![self] => 2, | ||
29 | kind if kind.is_trivia() => 0, | ||
30 | _ => 1, | ||
31 | })?; | ||
26 | let token: SyntaxToken = sema.descend_into_macros(token); | 32 | let token: SyntaxToken = sema.descend_into_macros(token); |
27 | 33 | ||
28 | let (ty, node) = sema.token_ancestors_with_macros(token).find_map(|node| { | 34 | let (ty, node) = sema.token_ancestors_with_macros(token).find_map(|node| { |
@@ -56,17 +62,6 @@ pub(crate) fn goto_type_definition( | |||
56 | Some(RangeInfo::new(node.text_range(), vec![nav])) | 62 | Some(RangeInfo::new(node.text_range(), vec![nav])) |
57 | } | 63 | } |
58 | 64 | ||
59 | fn pick_best(tokens: TokenAtOffset<SyntaxToken>) -> Option<SyntaxToken> { | ||
60 | return tokens.max_by_key(priority); | ||
61 | fn priority(n: &SyntaxToken) -> usize { | ||
62 | match n.kind() { | ||
63 | IDENT | INT_NUMBER | T![self] => 2, | ||
64 | kind if kind.is_trivia() => 0, | ||
65 | _ => 1, | ||
66 | } | ||
67 | } | ||
68 | } | ||
69 | |||
70 | #[cfg(test)] | 65 | #[cfg(test)] |
71 | mod tests { | 66 | mod tests { |
72 | use ide_db::base_db::FileRange; | 67 | use ide_db::base_db::FileRange; |
diff --git a/crates/ide/src/hover.rs b/crates/ide/src/hover.rs index c6d6bb74a..0eeea4efb 100644 --- a/crates/ide/src/hover.rs +++ b/crates/ide/src/hover.rs | |||
@@ -5,16 +5,13 @@ use ide_db::{ | |||
5 | defs::{Definition, NameClass, NameRefClass}, | 5 | defs::{Definition, NameClass, NameRefClass}, |
6 | helpers::{ | 6 | helpers::{ |
7 | generated_lints::{CLIPPY_LINTS, DEFAULT_LINTS, FEATURES}, | 7 | generated_lints::{CLIPPY_LINTS, DEFAULT_LINTS, FEATURES}, |
8 | FamousDefs, | 8 | pick_best_token, FamousDefs, |
9 | }, | 9 | }, |
10 | RootDatabase, | 10 | RootDatabase, |
11 | }; | 11 | }; |
12 | use itertools::Itertools; | 12 | use itertools::Itertools; |
13 | use stdx::format_to; | 13 | use stdx::format_to; |
14 | use syntax::{ | 14 | use syntax::{algo, ast, match_ast, AstNode, AstToken, Direction, SyntaxKind::*, SyntaxToken, T}; |
15 | algo, ast, match_ast, AstNode, AstToken, Direction, SyntaxKind::*, SyntaxToken, TokenAtOffset, | ||
16 | T, | ||
17 | }; | ||
18 | 15 | ||
19 | use crate::{ | 16 | use crate::{ |
20 | display::{macro_label, TryToNav}, | 17 | display::{macro_label, TryToNav}, |
@@ -80,7 +77,12 @@ pub(crate) fn hover( | |||
80 | ) -> Option<RangeInfo<HoverResult>> { | 77 | ) -> Option<RangeInfo<HoverResult>> { |
81 | let sema = hir::Semantics::new(db); | 78 | let sema = hir::Semantics::new(db); |
82 | let file = sema.parse(position.file_id).syntax().clone(); | 79 | let file = sema.parse(position.file_id).syntax().clone(); |
83 | let token = pick_best(file.token_at_offset(position.offset))?; | 80 | let token = pick_best_token(file.token_at_offset(position.offset), |kind| match kind { |
81 | IDENT | INT_NUMBER | LIFETIME_IDENT | T![self] | T![super] | T![crate] => 3, | ||
82 | T!['('] | T![')'] => 2, | ||
83 | kind if kind.is_trivia() => 0, | ||
84 | _ => 1, | ||
85 | })?; | ||
84 | let token = sema.descend_into_macros(token); | 86 | let token = sema.descend_into_macros(token); |
85 | 87 | ||
86 | let mut res = HoverResult::default(); | 88 | let mut res = HoverResult::default(); |
@@ -519,19 +521,6 @@ fn find_std_module(famous_defs: &FamousDefs, name: &str) -> Option<hir::Module> | |||
519 | .find(|module| module.name(db).map_or(false, |module| module.to_string() == name)) | 521 | .find(|module| module.name(db).map_or(false, |module| module.to_string() == name)) |
520 | } | 522 | } |
521 | 523 | ||
522 | fn pick_best(tokens: TokenAtOffset<SyntaxToken>) -> Option<SyntaxToken> { | ||
523 | return tokens.max_by_key(priority); | ||
524 | |||
525 | fn priority(n: &SyntaxToken) -> usize { | ||
526 | match n.kind() { | ||
527 | IDENT | INT_NUMBER | LIFETIME_IDENT | T![self] | T![super] | T![crate] => 3, | ||
528 | T!['('] | T![')'] => 2, | ||
529 | kind if kind.is_trivia() => 0, | ||
530 | _ => 1, | ||
531 | } | ||
532 | } | ||
533 | } | ||
534 | |||
535 | #[cfg(test)] | 524 | #[cfg(test)] |
536 | mod tests { | 525 | mod tests { |
537 | use expect_test::{expect, Expect}; | 526 | use expect_test::{expect, Expect}; |
diff --git a/crates/ide/src/lib.rs b/crates/ide/src/lib.rs index b978e36af..ca14533f3 100644 --- a/crates/ide/src/lib.rs +++ b/crates/ide/src/lib.rs | |||
@@ -439,7 +439,7 @@ impl Analysis { | |||
439 | self.with_db(|db| call_hierarchy::incoming_calls(db, position)) | 439 | self.with_db(|db| call_hierarchy::incoming_calls(db, position)) |
440 | } | 440 | } |
441 | 441 | ||
442 | /// Computes incoming calls for the given file position. | 442 | /// Computes outgoing calls for the given file position. |
443 | pub fn outgoing_calls(&self, position: FilePosition) -> Cancellable<Option<Vec<CallItem>>> { | 443 | pub fn outgoing_calls(&self, position: FilePosition) -> Cancellable<Option<Vec<CallItem>>> { |
444 | self.with_db(|db| call_hierarchy::outgoing_calls(db, position)) | 444 | self.with_db(|db| call_hierarchy::outgoing_calls(db, position)) |
445 | } | 445 | } |
diff --git a/crates/ide/src/move_item.rs b/crates/ide/src/move_item.rs index 246f10a0a..1223c2810 100644 --- a/crates/ide/src/move_item.rs +++ b/crates/ide/src/move_item.rs | |||
@@ -1,12 +1,9 @@ | |||
1 | use std::{iter::once, mem}; | 1 | use std::{iter::once, mem}; |
2 | 2 | ||
3 | use hir::Semantics; | 3 | use hir::Semantics; |
4 | use ide_db::{base_db::FileRange, RootDatabase}; | 4 | use ide_db::{base_db::FileRange, helpers::pick_best_token, RootDatabase}; |
5 | use itertools::Itertools; | 5 | use itertools::Itertools; |
6 | use syntax::{ | 6 | use syntax::{algo, ast, match_ast, AstNode, SyntaxElement, SyntaxKind, SyntaxNode, TextRange}; |
7 | algo, ast, match_ast, AstNode, SyntaxElement, SyntaxKind, SyntaxNode, SyntaxToken, TextRange, | ||
8 | TokenAtOffset, | ||
9 | }; | ||
10 | use text_edit::{TextEdit, TextEditBuilder}; | 7 | use text_edit::{TextEdit, TextEditBuilder}; |
11 | 8 | ||
12 | #[derive(Copy, Clone, Debug)] | 9 | #[derive(Copy, Clone, Debug)] |
@@ -36,7 +33,14 @@ pub(crate) fn move_item( | |||
36 | let file = sema.parse(range.file_id); | 33 | let file = sema.parse(range.file_id); |
37 | 34 | ||
38 | let item = if range.range.is_empty() { | 35 | let item = if range.range.is_empty() { |
39 | SyntaxElement::Token(pick_best(file.syntax().token_at_offset(range.range.start()))?) | 36 | SyntaxElement::Token(pick_best_token( |
37 | file.syntax().token_at_offset(range.range.start()), | ||
38 | |kind| match kind { | ||
39 | SyntaxKind::IDENT | SyntaxKind::LIFETIME_IDENT => 2, | ||
40 | kind if kind.is_trivia() => 0, | ||
41 | _ => 1, | ||
42 | }, | ||
43 | )?) | ||
40 | } else { | 44 | } else { |
41 | file.syntax().covering_element(range.range) | 45 | file.syntax().covering_element(range.range) |
42 | }; | 46 | }; |
@@ -170,18 +174,6 @@ fn replace_nodes<'a>( | |||
170 | edit.finish() | 174 | edit.finish() |
171 | } | 175 | } |
172 | 176 | ||
173 | fn pick_best(tokens: TokenAtOffset<SyntaxToken>) -> Option<SyntaxToken> { | ||
174 | return tokens.max_by_key(priority); | ||
175 | |||
176 | fn priority(n: &SyntaxToken) -> usize { | ||
177 | match n.kind() { | ||
178 | SyntaxKind::IDENT | SyntaxKind::LIFETIME_IDENT => 2, | ||
179 | kind if kind.is_trivia() => 0, | ||
180 | _ => 1, | ||
181 | } | ||
182 | } | ||
183 | } | ||
184 | |||
185 | #[cfg(test)] | 177 | #[cfg(test)] |
186 | mod tests { | 178 | mod tests { |
187 | use crate::fixture; | 179 | use crate::fixture; |
diff --git a/crates/ide_db/src/helpers.rs b/crates/ide_db/src/helpers.rs index d96028cbc..bc21977e3 100644 --- a/crates/ide_db/src/helpers.rs +++ b/crates/ide_db/src/helpers.rs | |||
@@ -10,7 +10,10 @@ use std::collections::VecDeque; | |||
10 | use base_db::FileId; | 10 | use base_db::FileId; |
11 | use either::Either; | 11 | use either::Either; |
12 | use hir::{Crate, Enum, ItemInNs, MacroDef, Module, ModuleDef, Name, ScopeDef, Semantics, Trait}; | 12 | use hir::{Crate, Enum, ItemInNs, MacroDef, Module, ModuleDef, Name, ScopeDef, Semantics, Trait}; |
13 | use syntax::ast::{self, make}; | 13 | use syntax::{ |
14 | ast::{self, make}, | ||
15 | SyntaxKind, SyntaxToken, TokenAtOffset, | ||
16 | }; | ||
14 | 17 | ||
15 | use crate::RootDatabase; | 18 | use crate::RootDatabase; |
16 | 19 | ||
@@ -22,6 +25,14 @@ pub fn item_name(db: &RootDatabase, item: ItemInNs) -> Option<Name> { | |||
22 | } | 25 | } |
23 | } | 26 | } |
24 | 27 | ||
28 | /// Picks the token with the highest rank returned by the passed in function. | ||
29 | pub fn pick_best_token( | ||
30 | tokens: TokenAtOffset<SyntaxToken>, | ||
31 | f: impl Fn(SyntaxKind) -> usize, | ||
32 | ) -> Option<SyntaxToken> { | ||
33 | tokens.max_by_key(move |t| f(t.kind())) | ||
34 | } | ||
35 | |||
25 | /// Converts the mod path struct into its ast representation. | 36 | /// Converts the mod path struct into its ast representation. |
26 | pub fn mod_path_to_ast(path: &hir::ModPath) -> ast::Path { | 37 | pub fn mod_path_to_ast(path: &hir::ModPath) -> ast::Path { |
27 | let _p = profile::span("mod_path_to_ast"); | 38 | let _p = profile::span("mod_path_to_ast"); |