aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/hir/src/source_analyzer.rs6
-rw-r--r--crates/ide_completion/src/completions/keyword.rs6
-rw-r--r--crates/ide_completion/src/context.rs63
-rw-r--r--crates/ide_completion/src/patterns.rs37
4 files changed, 44 insertions, 68 deletions
diff --git a/crates/hir/src/source_analyzer.rs b/crates/hir/src/source_analyzer.rs
index 3f940124c..37a050415 100644
--- a/crates/hir/src/source_analyzer.rs
+++ b/crates/hir/src/source_analyzer.rs
@@ -308,7 +308,11 @@ impl SourceAnalyzer {
308 } 308 }
309 } 309 }
310 310
311 resolve_hir_path_(db, &self.resolver, &hir_path, prefer_value_ns) 311 if parent().map_or(false, |it| ast::Visibility::can_cast(it.kind())) {
312 resolve_hir_path_qualifier(db, &self.resolver, &hir_path)
313 } else {
314 resolve_hir_path_(db, &self.resolver, &hir_path, prefer_value_ns)
315 }
312 } 316 }
313 317
314 pub(crate) fn record_literal_missing_fields( 318 pub(crate) fn record_literal_missing_fields(
diff --git a/crates/ide_completion/src/completions/keyword.rs b/crates/ide_completion/src/completions/keyword.rs
index 2c4ed1b00..fa6bcc955 100644
--- a/crates/ide_completion/src/completions/keyword.rs
+++ b/crates/ide_completion/src/completions/keyword.rs
@@ -2,7 +2,7 @@
2 2
3use std::iter; 3use std::iter;
4 4
5use syntax::SyntaxKind; 5use syntax::{SyntaxKind, T};
6 6
7use crate::{CompletionContext, CompletionItem, CompletionItemKind, CompletionKind, Completions}; 7use crate::{CompletionContext, CompletionItem, CompletionItemKind, CompletionKind, Completions};
8 8
@@ -54,7 +54,7 @@ pub(crate) fn complete_expr_keyword(acc: &mut Completions, ctx: &CompletionConte
54 add_keyword(ctx, acc, "where", "where "); 54 add_keyword(ctx, acc, "where", "where ");
55 return; 55 return;
56 } 56 }
57 if ctx.unsafe_is_prev { 57 if ctx.previous_token_is(T![unsafe]) {
58 if ctx.has_item_list_or_source_file_parent || ctx.block_expr_parent { 58 if ctx.has_item_list_or_source_file_parent || ctx.block_expr_parent {
59 add_keyword(ctx, acc, "fn", "fn $1($2) {\n $0\n}") 59 add_keyword(ctx, acc, "fn", "fn $1($2) {\n $0\n}")
60 } 60 }
@@ -92,7 +92,7 @@ pub(crate) fn complete_expr_keyword(acc: &mut Completions, ctx: &CompletionConte
92 add_keyword(ctx, acc, "for", "for $1 in $2 {\n $0\n}"); 92 add_keyword(ctx, acc, "for", "for $1 in $2 {\n $0\n}");
93 } 93 }
94 94
95 if ctx.if_is_prev || ctx.block_expr_parent { 95 if ctx.previous_token_is(T![if]) || ctx.previous_token_is(T![while]) || ctx.block_expr_parent {
96 add_keyword(ctx, acc, "let", "let "); 96 add_keyword(ctx, acc, "let", "let ");
97 } 97 }
98 98
diff --git a/crates/ide_completion/src/context.rs b/crates/ide_completion/src/context.rs
index 2f3fb1710..85c7edabb 100644
--- a/crates/ide_completion/src/context.rs
+++ b/crates/ide_completion/src/context.rs
@@ -1,25 +1,26 @@
1//! See `CompletionContext` structure. 1//! See `CompletionContext` structure.
2 2
3use hir::{Local, ScopeDef, Semantics, SemanticsScope, Type}; 3use hir::{Local, ScopeDef, Semantics, SemanticsScope, Type};
4use ide_db::base_db::{FilePosition, SourceDatabase}; 4use ide_db::{
5use ide_db::{call_info::ActiveParameter, RootDatabase}; 5 base_db::{FilePosition, SourceDatabase},
6 call_info::ActiveParameter,
7 RootDatabase,
8};
6use syntax::{ 9use syntax::{
7 algo::find_node_at_offset, 10 algo::find_node_at_offset,
8 ast::{self, NameOrNameRef, NameOwner}, 11 ast::{self, NameOrNameRef, NameOwner},
9 match_ast, AstNode, NodeOrToken, 12 match_ast, AstNode, NodeOrToken,
10 SyntaxKind::*, 13 SyntaxKind::{self, *},
11 SyntaxNode, SyntaxToken, TextRange, TextSize, 14 SyntaxNode, SyntaxToken, TextRange, TextSize, T,
12}; 15};
13
14use text_edit::Indel; 16use text_edit::Indel;
15 17
16use crate::{ 18use crate::{
17 patterns::{ 19 patterns::{
18 fn_is_prev, for_is_prev2, has_bind_pat_parent, has_block_expr_parent, 20 for_is_prev2, has_bind_pat_parent, has_block_expr_parent, has_field_list_parent,
19 has_field_list_parent, has_impl_as_prev_sibling, has_impl_parent, 21 has_impl_as_prev_sibling, has_impl_parent, has_item_list_or_source_file_parent,
20 has_item_list_or_source_file_parent, has_ref_parent, has_trait_as_prev_sibling, 22 has_ref_parent, has_trait_as_prev_sibling, has_trait_parent, inside_impl_trait_block,
21 has_trait_parent, if_is_prev, inside_impl_trait_block, is_in_loop_body, is_match_arm, 23 is_in_loop_body, is_match_arm, previous_token,
22 unsafe_is_prev,
23 }, 24 },
24 CompletionConfig, 25 CompletionConfig,
25}; 26};
@@ -81,25 +82,26 @@ pub(crate) struct CompletionContext<'a> {
81 pub(super) is_path_type: bool, 82 pub(super) is_path_type: bool,
82 pub(super) has_type_args: bool, 83 pub(super) has_type_args: bool,
83 pub(super) attribute_under_caret: Option<ast::Attr>, 84 pub(super) attribute_under_caret: Option<ast::Attr>,
85 pub(super) locals: Vec<(String, Local)>,
86
84 pub(super) mod_declaration_under_caret: Option<ast::Module>, 87 pub(super) mod_declaration_under_caret: Option<ast::Module>,
85 pub(super) unsafe_is_prev: bool, 88 pub(super) has_trait_parent: bool,
86 pub(super) if_is_prev: bool, 89 pub(super) has_impl_parent: bool,
90
91 // keyword patterns
92 pub(super) previous_token: Option<SyntaxToken>,
87 pub(super) block_expr_parent: bool, 93 pub(super) block_expr_parent: bool,
88 pub(super) bind_pat_parent: bool, 94 pub(super) bind_pat_parent: bool,
89 pub(super) ref_pat_parent: bool, 95 pub(super) ref_pat_parent: bool,
90 pub(super) in_loop_body: bool, 96 pub(super) in_loop_body: bool,
91 pub(super) has_trait_parent: bool,
92 pub(super) has_impl_parent: bool,
93 pub(super) inside_impl_trait_block: bool,
94 pub(super) has_field_list_parent: bool, 97 pub(super) has_field_list_parent: bool,
95 pub(super) trait_as_prev_sibling: bool, 98 pub(super) trait_as_prev_sibling: bool,
96 pub(super) impl_as_prev_sibling: bool, 99 pub(super) impl_as_prev_sibling: bool,
97 pub(super) is_match_arm: bool, 100 pub(super) is_match_arm: bool,
98 pub(super) has_item_list_or_source_file_parent: bool, 101 pub(super) has_item_list_or_source_file_parent: bool,
99 pub(super) for_is_prev2: bool,
100 pub(super) fn_is_prev: bool,
101 pub(super) incomplete_let: bool, 102 pub(super) incomplete_let: bool,
102 pub(super) locals: Vec<(String, Local)>, 103
104 no_completion_required: bool,
103} 105}
104 106
105impl<'a> CompletionContext<'a> { 107impl<'a> CompletionContext<'a> {
@@ -175,22 +177,19 @@ impl<'a> CompletionContext<'a> {
175 has_type_args: false, 177 has_type_args: false,
176 attribute_under_caret: None, 178 attribute_under_caret: None,
177 mod_declaration_under_caret: None, 179 mod_declaration_under_caret: None,
178 unsafe_is_prev: false, 180 previous_token: None,
179 if_is_prev: false,
180 block_expr_parent: false, 181 block_expr_parent: false,
181 bind_pat_parent: false, 182 bind_pat_parent: false,
182 ref_pat_parent: false, 183 ref_pat_parent: false,
183 in_loop_body: false, 184 in_loop_body: false,
184 has_trait_parent: false, 185 has_trait_parent: false,
185 has_impl_parent: false, 186 has_impl_parent: false,
186 inside_impl_trait_block: false,
187 has_field_list_parent: false, 187 has_field_list_parent: false,
188 trait_as_prev_sibling: false, 188 trait_as_prev_sibling: false,
189 impl_as_prev_sibling: false, 189 impl_as_prev_sibling: false,
190 is_match_arm: false, 190 is_match_arm: false,
191 has_item_list_or_source_file_parent: false, 191 has_item_list_or_source_file_parent: false,
192 for_is_prev2: false, 192 no_completion_required: false,
193 fn_is_prev: false,
194 incomplete_let: false, 193 incomplete_let: false,
195 locals, 194 locals,
196 }; 195 };
@@ -245,7 +244,7 @@ impl<'a> CompletionContext<'a> {
245 /// Exception for this case is `impl Trait for Foo`, where we would like to hint trait method names. 244 /// Exception for this case is `impl Trait for Foo`, where we would like to hint trait method names.
246 /// - `for _ i$0` -- obviously, it'll be "in" keyword. 245 /// - `for _ i$0` -- obviously, it'll be "in" keyword.
247 pub(crate) fn no_completion_required(&self) -> bool { 246 pub(crate) fn no_completion_required(&self) -> bool {
248 (self.fn_is_prev && !self.inside_impl_trait_block) || self.for_is_prev2 247 self.no_completion_required
249 } 248 }
250 249
251 /// The range of the identifier that is being completed. 250 /// The range of the identifier that is being completed.
@@ -264,33 +263,39 @@ impl<'a> CompletionContext<'a> {
264 } 263 }
265 } 264 }
266 265
266 pub(crate) fn previous_token_is(&self, kind: SyntaxKind) -> bool {
267 self.previous_token.as_ref().map_or(false, |tok| tok.kind() == kind)
268 }
269
267 fn fill_keyword_patterns(&mut self, file_with_fake_ident: &SyntaxNode, offset: TextSize) { 270 fn fill_keyword_patterns(&mut self, file_with_fake_ident: &SyntaxNode, offset: TextSize) {
268 let fake_ident_token = file_with_fake_ident.token_at_offset(offset).right_biased().unwrap(); 271 let fake_ident_token = file_with_fake_ident.token_at_offset(offset).right_biased().unwrap();
269 let syntax_element = NodeOrToken::Token(fake_ident_token); 272 let syntax_element = NodeOrToken::Token(fake_ident_token);
273 self.previous_token = previous_token(syntax_element.clone());
270 self.block_expr_parent = has_block_expr_parent(syntax_element.clone()); 274 self.block_expr_parent = has_block_expr_parent(syntax_element.clone());
271 self.unsafe_is_prev = unsafe_is_prev(syntax_element.clone());
272 self.if_is_prev = if_is_prev(syntax_element.clone());
273 self.bind_pat_parent = has_bind_pat_parent(syntax_element.clone()); 275 self.bind_pat_parent = has_bind_pat_parent(syntax_element.clone());
274 self.ref_pat_parent = has_ref_parent(syntax_element.clone()); 276 self.ref_pat_parent = has_ref_parent(syntax_element.clone());
275 self.in_loop_body = is_in_loop_body(syntax_element.clone()); 277 self.in_loop_body = is_in_loop_body(syntax_element.clone());
276 self.has_trait_parent = has_trait_parent(syntax_element.clone()); 278 self.has_trait_parent = has_trait_parent(syntax_element.clone());
277 self.has_impl_parent = has_impl_parent(syntax_element.clone()); 279 self.has_impl_parent = has_impl_parent(syntax_element.clone());
278 self.inside_impl_trait_block = inside_impl_trait_block(syntax_element.clone());
279 self.has_field_list_parent = has_field_list_parent(syntax_element.clone()); 280 self.has_field_list_parent = has_field_list_parent(syntax_element.clone());
280 self.impl_as_prev_sibling = has_impl_as_prev_sibling(syntax_element.clone()); 281 self.impl_as_prev_sibling = has_impl_as_prev_sibling(syntax_element.clone());
281 self.trait_as_prev_sibling = has_trait_as_prev_sibling(syntax_element.clone()); 282 self.trait_as_prev_sibling = has_trait_as_prev_sibling(syntax_element.clone());
282 self.is_match_arm = is_match_arm(syntax_element.clone()); 283 self.is_match_arm = is_match_arm(syntax_element.clone());
284
283 self.has_item_list_or_source_file_parent = 285 self.has_item_list_or_source_file_parent =
284 has_item_list_or_source_file_parent(syntax_element.clone()); 286 has_item_list_or_source_file_parent(syntax_element.clone());
285 self.mod_declaration_under_caret = 287 self.mod_declaration_under_caret =
286 find_node_at_offset::<ast::Module>(&file_with_fake_ident, offset) 288 find_node_at_offset::<ast::Module>(&file_with_fake_ident, offset)
287 .filter(|module| module.item_list().is_none()); 289 .filter(|module| module.item_list().is_none());
288 self.for_is_prev2 = for_is_prev2(syntax_element.clone());
289 self.fn_is_prev = fn_is_prev(syntax_element.clone());
290 self.incomplete_let = 290 self.incomplete_let =
291 syntax_element.ancestors().take(6).find_map(ast::LetStmt::cast).map_or(false, |it| { 291 syntax_element.ancestors().take(6).find_map(ast::LetStmt::cast).map_or(false, |it| {
292 it.syntax().text_range().end() == syntax_element.text_range().end() 292 it.syntax().text_range().end() == syntax_element.text_range().end()
293 }); 293 });
294
295 let inside_impl_trait_block = inside_impl_trait_block(syntax_element.clone());
296 let fn_is_prev = self.previous_token_is(T![fn]);
297 let for_is_prev2 = for_is_prev2(syntax_element.clone());
298 self.no_completion_required = (fn_is_prev && !inside_impl_trait_block) || for_is_prev2;
294 } 299 }
295 300
296 fn fill_impl_def(&mut self) { 301 fn fill_impl_def(&mut self) {
diff --git a/crates/ide_completion/src/patterns.rs b/crates/ide_completion/src/patterns.rs
index d82564381..3d8a83ed8 100644
--- a/crates/ide_completion/src/patterns.rs
+++ b/crates/ide_completion/src/patterns.rs
@@ -115,36 +115,8 @@ fn test_is_match_arm() {
115 check_pattern_is_applicable(r"fn my_fn() { match () { () => m$0 } }", is_match_arm); 115 check_pattern_is_applicable(r"fn my_fn() { match () { () => m$0 } }", is_match_arm);
116} 116}
117 117
118pub(crate) fn unsafe_is_prev(element: SyntaxElement) -> bool { 118pub(crate) fn previous_token(element: SyntaxElement) -> Option<SyntaxToken> {
119 element 119 element.into_token().and_then(|it| previous_non_trivia_token(it))
120 .into_token()
121 .and_then(|it| previous_non_trivia_token(it))
122 .filter(|it| it.kind() == T![unsafe])
123 .is_some()
124}
125#[test]
126fn test_unsafe_is_prev() {
127 check_pattern_is_applicable(r"unsafe i$0", unsafe_is_prev);
128}
129
130pub(crate) fn if_is_prev(element: SyntaxElement) -> bool {
131 element
132 .into_token()
133 .and_then(|it| previous_non_trivia_token(it))
134 .filter(|it| it.kind() == T![if])
135 .is_some()
136}
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() == T![fn])
143 .is_some()
144}
145#[test]
146fn test_fn_is_prev() {
147 check_pattern_is_applicable(r"fn l$0", fn_is_prev);
148} 120}
149 121
150/// Check if the token previous to the previous one is `for`. 122/// Check if the token previous to the previous one is `for`.
@@ -162,11 +134,6 @@ fn test_for_is_prev2() {
162 check_pattern_is_applicable(r"for i i$0", for_is_prev2); 134 check_pattern_is_applicable(r"for i i$0", for_is_prev2);
163} 135}
164 136
165#[test]
166fn test_if_is_prev() {
167 check_pattern_is_applicable(r"if l$0", if_is_prev);
168}
169
170pub(crate) fn has_trait_as_prev_sibling(element: SyntaxElement) -> bool { 137pub(crate) fn has_trait_as_prev_sibling(element: SyntaxElement) -> bool {
171 previous_sibling_or_ancestor_sibling(element).filter(|it| it.kind() == TRAIT).is_some() 138 previous_sibling_or_ancestor_sibling(element).filter(|it| it.kind() == TRAIT).is_some()
172} 139}