aboutsummaryrefslogtreecommitdiff
path: root/crates/ide/src/completion/patterns.rs
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2020-10-17 11:31:37 +0100
committerGitHub <[email protected]>2020-10-17 11:31:37 +0100
commitb1315be010f0d9f67ee4794cb57f7d1baa88a30d (patch)
treeb4259ce1810c3cd6c2bea62bae499415b764728d /crates/ide/src/completion/patterns.rs
parent59483c217662fc5d89ef9da1cb93760e14a48418 (diff)
parent99c435939c941fe5216c39bc136769098abbbfea (diff)
Merge #6262
6262: Do not spawn redundant hints r=SomeoneToIgnore a=popzxc Closes #5206 This is a second part of the fix (first was #5997). This PR adds a new method to the `CompletionContext`: `no_completion_required`. If this method returns `true`, it essentially means that user is unlikely to expect any hints from the IDE at this cursor position. Currently, checks for the following cases were added: - Previous item is `fn`: user creates a new function, names of existing functions won't be helpful. Exception for this case is `impl Foo for Bar` -- we must suggest trait function names. - User entered `for _ i<|>`: it's obviously going to be `in` keyword, any hints here will be confusing. More checks may be added there later, but currently I've only figured two cases. ![no_redundant_hints](https://user-images.githubusercontent.com/12111581/96332088-da4d2a00-106a-11eb-89a1-1159ece18f9d.png) Co-authored-by: Igor Aleksanov <[email protected]>
Diffstat (limited to 'crates/ide/src/completion/patterns.rs')
-rw-r--r--crates/ide/src/completion/patterns.rs48
1 files changed, 47 insertions, 1 deletions
diff --git a/crates/ide/src/completion/patterns.rs b/crates/ide/src/completion/patterns.rs
index b17ddf133..cf6d5947d 100644
--- a/crates/ide/src/completion/patterns.rs
+++ b/crates/ide/src/completion/patterns.rs
@@ -9,7 +9,7 @@ use syntax::{
9}; 9};
10 10
11#[cfg(test)] 11#[cfg(test)]
12use crate::completion::test_utils::check_pattern_is_applicable; 12use crate::completion::test_utils::{check_pattern_is_applicable, check_pattern_is_not_applicable};
13 13
14pub(crate) fn has_trait_parent(element: SyntaxElement) -> bool { 14pub(crate) fn has_trait_parent(element: SyntaxElement) -> bool {
15 not_same_range_ancestor(element) 15 not_same_range_ancestor(element)
@@ -34,6 +34,25 @@ pub(crate) fn has_impl_parent(element: SyntaxElement) -> bool {
34fn test_has_impl_parent() { 34fn test_has_impl_parent() {
35 check_pattern_is_applicable(r"impl A { f<|> }", has_impl_parent); 35 check_pattern_is_applicable(r"impl A { f<|> }", has_impl_parent);
36} 36}
37
38pub(crate) fn inside_impl_trait_block(element: SyntaxElement) -> bool {
39 // Here we search `impl` keyword up through the all ancestors, unlike in `has_impl_parent`,
40 // where we only check the first parent with different text range.
41 element
42 .ancestors()
43 .find(|it| it.kind() == IMPL)
44 .map(|it| ast::Impl::cast(it).unwrap())
45 .map(|it| it.trait_().is_some())
46 .unwrap_or(false)
47}
48#[test]
49fn test_inside_impl_trait_block() {
50 check_pattern_is_applicable(r"impl Foo for Bar { f<|> }", inside_impl_trait_block);
51 check_pattern_is_applicable(r"impl Foo for Bar { fn f<|> }", inside_impl_trait_block);
52 check_pattern_is_not_applicable(r"impl A { f<|> }", inside_impl_trait_block);
53 check_pattern_is_not_applicable(r"impl A { fn f<|> }", inside_impl_trait_block);
54}
55
37pub(crate) fn has_field_list_parent(element: SyntaxElement) -> bool { 56pub(crate) fn has_field_list_parent(element: SyntaxElement) -> bool {
38 not_same_range_ancestor(element).filter(|it| it.kind() == RECORD_FIELD_LIST).is_some() 57 not_same_range_ancestor(element).filter(|it| it.kind() == RECORD_FIELD_LIST).is_some()
39} 58}
@@ -116,6 +135,33 @@ pub(crate) fn if_is_prev(element: SyntaxElement) -> bool {
116 .is_some() 135 .is_some()
117} 136}
118 137
138pub(crate) fn fn_is_prev(element: SyntaxElement) -> bool {
139 element
140 .into_token()
141 .and_then(|it| previous_non_trivia_token(it))
142 .filter(|it| it.kind() == FN_KW)
143 .is_some()
144}
145#[test]
146fn test_fn_is_prev() {
147 check_pattern_is_applicable(r"fn l<|>", fn_is_prev);
148}
149
150/// Check if the token previous to the previous one is `for`.
151/// For example, `for _ i<|>` => true.
152pub(crate) fn for_is_prev2(element: SyntaxElement) -> bool {
153 element
154 .into_token()
155 .and_then(|it| previous_non_trivia_token(it))
156 .and_then(|it| previous_non_trivia_token(it))
157 .filter(|it| it.kind() == FOR_KW)
158 .is_some()
159}
160#[test]
161fn test_for_is_prev2() {
162 check_pattern_is_applicable(r"for i i<|>", for_is_prev2);
163}
164
119#[test] 165#[test]
120fn test_if_is_prev() { 166fn test_if_is_prev() {
121 check_pattern_is_applicable(r"if l<|>", if_is_prev); 167 check_pattern_is_applicable(r"if l<|>", if_is_prev);