aboutsummaryrefslogtreecommitdiff
path: root/crates/ide_completion/src/context.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ide_completion/src/context.rs')
-rw-r--r--crates/ide_completion/src/context.rs38
1 files changed, 22 insertions, 16 deletions
diff --git a/crates/ide_completion/src/context.rs b/crates/ide_completion/src/context.rs
index 6d57da06a..a60b8b09d 100644
--- a/crates/ide_completion/src/context.rs
+++ b/crates/ide_completion/src/context.rs
@@ -4,8 +4,11 @@ use hir::{Local, ScopeDef, Semantics, SemanticsScope, Type};
4use ide_db::base_db::{FilePosition, SourceDatabase}; 4use ide_db::base_db::{FilePosition, SourceDatabase};
5use ide_db::{call_info::ActiveParameter, RootDatabase}; 5use ide_db::{call_info::ActiveParameter, RootDatabase};
6use syntax::{ 6use syntax::{
7 algo::find_node_at_offset, ast, match_ast, AstNode, NodeOrToken, SyntaxKind::*, SyntaxNode, 7 algo::find_node_at_offset,
8 SyntaxToken, TextRange, TextSize, 8 ast::{self, NameOrNameRef, NameOwner},
9 match_ast, AstNode, NodeOrToken,
10 SyntaxKind::*,
11 SyntaxNode, SyntaxToken, TextRange, TextSize,
9}; 12};
10 13
11use text_edit::Indel; 14use text_edit::Indel;
@@ -35,7 +38,7 @@ pub(crate) struct CompletionContext<'a> {
35 /// The token before the cursor, in the macro-expanded file. 38 /// The token before the cursor, in the macro-expanded file.
36 pub(super) token: SyntaxToken, 39 pub(super) token: SyntaxToken,
37 pub(super) krate: Option<hir::Crate>, 40 pub(super) krate: Option<hir::Crate>,
38 pub(super) expected_name: Option<String>, 41 pub(super) expected_name: Option<NameOrNameRef>,
39 pub(super) expected_type: Option<Type>, 42 pub(super) expected_type: Option<Type>,
40 pub(super) name_ref_syntax: Option<ast::NameRef>, 43 pub(super) name_ref_syntax: Option<ast::NameRef>,
41 pub(super) function_syntax: Option<ast::Fn>, 44 pub(super) function_syntax: Option<ast::Fn>,
@@ -292,13 +295,13 @@ impl<'a> CompletionContext<'a> {
292 file_with_fake_ident: SyntaxNode, 295 file_with_fake_ident: SyntaxNode,
293 offset: TextSize, 296 offset: TextSize,
294 ) { 297 ) {
295 let expected = { 298 let (expected_type, expected_name) = {
296 let mut node = match self.token.parent() { 299 let mut node = match self.token.parent() {
297 Some(it) => it, 300 Some(it) => it,
298 None => return, 301 None => return,
299 }; 302 };
300 loop { 303 loop {
301 let ret = match_ast! { 304 break match_ast! {
302 match node { 305 match node {
303 ast::LetStmt(it) => { 306 ast::LetStmt(it) => {
304 cov_mark::hit!(expected_type_let_with_leading_char); 307 cov_mark::hit!(expected_type_let_with_leading_char);
@@ -306,7 +309,7 @@ impl<'a> CompletionContext<'a> {
306 let ty = it.pat() 309 let ty = it.pat()
307 .and_then(|pat| self.sema.type_of_pat(&pat)); 310 .and_then(|pat| self.sema.type_of_pat(&pat));
308 let name = if let Some(ast::Pat::IdentPat(ident)) = it.pat() { 311 let name = if let Some(ast::Pat::IdentPat(ident)) = it.pat() {
309 Some(ident.syntax().text().to_string()) 312 ident.name().map(NameOrNameRef::Name)
310 } else { 313 } else {
311 None 314 None
312 }; 315 };
@@ -319,7 +322,10 @@ impl<'a> CompletionContext<'a> {
319 ActiveParameter::at_token( 322 ActiveParameter::at_token(
320 &self.sema, 323 &self.sema,
321 self.token.clone(), 324 self.token.clone(),
322 ).map(|ap| (Some(ap.ty), Some(ap.name))) 325 ).map(|ap| {
326 let name = ap.ident().map(NameOrNameRef::Name);
327 (Some(ap.ty), name)
328 })
323 .unwrap_or((None, None)) 329 .unwrap_or((None, None))
324 }, 330 },
325 ast::RecordExprFieldList(_it) => { 331 ast::RecordExprFieldList(_it) => {
@@ -327,10 +333,10 @@ impl<'a> CompletionContext<'a> {
327 self.token.prev_sibling_or_token() 333 self.token.prev_sibling_or_token()
328 .and_then(|se| se.into_node()) 334 .and_then(|se| se.into_node())
329 .and_then(|node| ast::RecordExprField::cast(node)) 335 .and_then(|node| ast::RecordExprField::cast(node))
330 .and_then(|rf| self.sema.resolve_record_field(&rf)) 336 .and_then(|rf| self.sema.resolve_record_field(&rf).zip(Some(rf)))
331 .map(|f|( 337 .map(|(f, rf)|(
332 Some(f.0.signature_ty(self.db)), 338 Some(f.0.signature_ty(self.db)),
333 Some(f.0.name(self.db).to_string()), 339 rf.field_name().map(NameOrNameRef::NameRef),
334 )) 340 ))
335 .unwrap_or((None, None)) 341 .unwrap_or((None, None))
336 }, 342 },
@@ -340,7 +346,7 @@ impl<'a> CompletionContext<'a> {
340 .resolve_record_field(&it) 346 .resolve_record_field(&it)
341 .map(|f|( 347 .map(|f|(
342 Some(f.0.signature_ty(self.db)), 348 Some(f.0.signature_ty(self.db)),
343 Some(f.0.name(self.db).to_string()), 349 it.field_name().map(NameOrNameRef::NameRef),
344 )) 350 ))
345 .unwrap_or((None, None)) 351 .unwrap_or((None, None))
346 }, 352 },
@@ -378,12 +384,10 @@ impl<'a> CompletionContext<'a> {
378 }, 384 },
379 } 385 }
380 }; 386 };
381
382 break ret;
383 } 387 }
384 }; 388 };
385 self.expected_type = expected.0; 389 self.expected_type = expected_type;
386 self.expected_name = expected.1; 390 self.expected_name = expected_name;
387 self.attribute_under_caret = find_node_at_offset(&file_with_fake_ident, offset); 391 self.attribute_under_caret = find_node_at_offset(&file_with_fake_ident, offset);
388 392
389 // First, let's try to complete a reference to some declaration. 393 // First, let's try to complete a reference to some declaration.
@@ -631,7 +635,9 @@ mod tests {
631 .map(|t| t.display_test(&db).to_string()) 635 .map(|t| t.display_test(&db).to_string())
632 .unwrap_or("?".to_owned()); 636 .unwrap_or("?".to_owned());
633 637
634 let name = completion_context.expected_name.unwrap_or("?".to_owned()); 638 let name = completion_context
639 .expected_name
640 .map_or_else(|| "?".to_owned(), |name| name.to_string());
635 641
636 expect.assert_eq(&format!("ty: {}, name: {}", ty, name)); 642 expect.assert_eq(&format!("ty: {}, name: {}", ty, name));
637 } 643 }