aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLukas Wirth <[email protected]>2021-06-22 16:28:07 +0100
committerLukas Wirth <[email protected]>2021-06-22 16:50:15 +0100
commitf615efdfc3b4655e4f74068769905404cd911b5e (patch)
tree8e7d42ad63269c668b189c0a59d55ebd53328f90
parent4e2ec914f4b9609d162c3fd1776e8d293428fe5a (diff)
Factor out `pick_best_token` ide pattern into `ide_db`
-rw-r--r--crates/ide/src/call_hierarchy.rs3
-rw-r--r--crates/ide/src/doc_links.rs24
-rw-r--r--crates/ide/src/expand_macro.rs22
-rw-r--r--crates/ide/src/goto_definition.rs23
-rw-r--r--crates/ide/src/goto_type_definition.rs21
-rw-r--r--crates/ide/src/hover.rs27
-rw-r--r--crates/ide/src/lib.rs2
-rw-r--r--crates/ide/src/move_item.rs28
-rw-r--r--crates/ide_db/src/helpers.rs13
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 @@
3use indexmap::IndexMap; 3use indexmap::IndexMap;
4 4
5use hir::Semantics; 5use hir::Semantics;
6use ide_db::call_info::FnCallNode; 6use ide_db::{call_info::FnCallNode, RootDatabase};
7use ide_db::RootDatabase;
8use syntax::{ast, AstNode, TextRange}; 7use syntax::{ast, AstNode, TextRange};
9 8
10use crate::{ 9use 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};
17use ide_db::{ 17use ide_db::{
18 defs::{Definition, NameClass, NameRefClass}, 18 defs::{Definition, NameClass, NameRefClass},
19 helpers::pick_best_token,
19 RootDatabase, 20 RootDatabase,
20}; 21};
21use syntax::{ 22use syntax::{ast, match_ast, AstNode, SyntaxKind::*, SyntaxNode, TextRange, T};
22 ast, match_ast, AstNode, SyntaxKind::*, SyntaxNode, SyntaxToken, TextRange, TokenAtOffset, T,
23};
24 23
25use crate::{FilePosition, Semantics}; 24use 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
525fn 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)]
538mod tests { 530mod 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 @@
1use std::iter; 1use std::iter;
2 2
3use hir::Semantics; 3use hir::Semantics;
4use ide_db::RootDatabase; 4use ide_db::{helpers::pick_best_token, RootDatabase};
5use syntax::{ 5use 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
10use crate::FilePosition; 7use 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
60fn 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
70fn expand_macro_recur( 60fn 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};
5use ide_db::{ 5use 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};
10use syntax::{ 11use syntax::{ast, match_ast, AstNode, AstToken, SyntaxKind::*, SyntaxToken, TextRange, T};
11 ast, match_ast, AstNode, AstToken, SyntaxKind::*, SyntaxToken, TextRange, TokenAtOffset, T,
12};
13 12
14use crate::{ 13use 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
131fn 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
142pub(crate) fn reference_definition( 135pub(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 @@
1use ide_db::base_db::Upcast; 1use ide_db::base_db::Upcast;
2use ide_db::helpers::pick_best_token;
2use ide_db::RootDatabase; 3use ide_db::RootDatabase;
3use syntax::{ast, match_ast, AstNode, SyntaxKind::*, SyntaxToken, TokenAtOffset, T}; 4use syntax::{ast, match_ast, AstNode, SyntaxKind::*, SyntaxToken, T};
4 5
5use crate::{display::TryToNav, FilePosition, NavigationTarget, RangeInfo}; 6use 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
59fn 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)]
71mod tests { 66mod 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};
12use itertools::Itertools; 12use itertools::Itertools;
13use stdx::format_to; 13use stdx::format_to;
14use syntax::{ 14use 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
19use crate::{ 16use 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
522fn 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)]
536mod tests { 525mod 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 @@
1use std::{iter::once, mem}; 1use std::{iter::once, mem};
2 2
3use hir::Semantics; 3use hir::Semantics;
4use ide_db::{base_db::FileRange, RootDatabase}; 4use ide_db::{base_db::FileRange, helpers::pick_best_token, RootDatabase};
5use itertools::Itertools; 5use itertools::Itertools;
6use syntax::{ 6use syntax::{algo, ast, match_ast, AstNode, SyntaxElement, SyntaxKind, SyntaxNode, TextRange};
7 algo, ast, match_ast, AstNode, SyntaxElement, SyntaxKind, SyntaxNode, SyntaxToken, TextRange,
8 TokenAtOffset,
9};
10use text_edit::{TextEdit, TextEditBuilder}; 7use 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
173fn 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)]
186mod tests { 178mod 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;
10use base_db::FileId; 10use base_db::FileId;
11use either::Either; 11use either::Either;
12use hir::{Crate, Enum, ItemInNs, MacroDef, Module, ModuleDef, Name, ScopeDef, Semantics, Trait}; 12use hir::{Crate, Enum, ItemInNs, MacroDef, Module, ModuleDef, Name, ScopeDef, Semantics, Trait};
13use syntax::ast::{self, make}; 13use syntax::{
14 ast::{self, make},
15 SyntaxKind, SyntaxToken, TokenAtOffset,
16};
14 17
15use crate::RootDatabase; 18use 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.
29pub 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.
26pub fn mod_path_to_ast(path: &hir::ModPath) -> ast::Path { 37pub 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");