diff options
-rw-r--r-- | crates/ide/src/syntax_highlighting/inject.rs | 2 | ||||
-rw-r--r-- | crates/ide_completion/src/context.rs | 38 | ||||
-rw-r--r-- | crates/ide_completion/src/render.rs | 5 | ||||
-rw-r--r-- | crates/ide_db/src/call_info.rs | 14 | ||||
-rw-r--r-- | crates/syntax/src/ast/node_ext.rs | 9 |
5 files changed, 44 insertions, 24 deletions
diff --git a/crates/ide/src/syntax_highlighting/inject.rs b/crates/ide/src/syntax_highlighting/inject.rs index 00493a6b5..8e0940184 100644 --- a/crates/ide/src/syntax_highlighting/inject.rs +++ b/crates/ide/src/syntax_highlighting/inject.rs | |||
@@ -23,7 +23,7 @@ pub(super) fn ra_fixture( | |||
23 | expanded: SyntaxToken, | 23 | expanded: SyntaxToken, |
24 | ) -> Option<()> { | 24 | ) -> Option<()> { |
25 | let active_parameter = ActiveParameter::at_token(&sema, expanded)?; | 25 | let active_parameter = ActiveParameter::at_token(&sema, expanded)?; |
26 | if !active_parameter.name.starts_with("ra_fixture") { | 26 | if !active_parameter.ident().map_or(false, |name| name.text().starts_with("ra_fixture")) { |
27 | return None; | 27 | return None; |
28 | } | 28 | } |
29 | let value = literal.value()?; | 29 | let value = literal.value()?; |
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}; | |||
4 | use ide_db::base_db::{FilePosition, SourceDatabase}; | 4 | use ide_db::base_db::{FilePosition, SourceDatabase}; |
5 | use ide_db::{call_info::ActiveParameter, RootDatabase}; | 5 | use ide_db::{call_info::ActiveParameter, RootDatabase}; |
6 | use syntax::{ | 6 | use 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 | ||
11 | use text_edit::Indel; | 14 | use 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 | } |
diff --git a/crates/ide_completion/src/render.rs b/crates/ide_completion/src/render.rs index 12921e12b..2b6e9ebd1 100644 --- a/crates/ide_completion/src/render.rs +++ b/crates/ide_completion/src/render.rs | |||
@@ -243,7 +243,7 @@ impl<'a> Render<'a> { | |||
243 | 243 | ||
244 | item.set_relevance(CompletionRelevance { | 244 | item.set_relevance(CompletionRelevance { |
245 | exact_type_match: compute_exact_type_match(self.ctx.completion, &ty), | 245 | exact_type_match: compute_exact_type_match(self.ctx.completion, &ty), |
246 | exact_name_match: compute_exact_name_match(self.ctx.completion, local_name.clone()), | 246 | exact_name_match: compute_exact_name_match(self.ctx.completion, &local_name), |
247 | is_local: true, | 247 | is_local: true, |
248 | ..CompletionRelevance::default() | 248 | ..CompletionRelevance::default() |
249 | }); | 249 | }); |
@@ -319,8 +319,7 @@ fn compute_exact_type_match(ctx: &CompletionContext, completion_ty: &hir::Type) | |||
319 | 319 | ||
320 | fn compute_exact_name_match(ctx: &CompletionContext, completion_name: impl Into<String>) -> bool { | 320 | fn compute_exact_name_match(ctx: &CompletionContext, completion_name: impl Into<String>) -> bool { |
321 | let completion_name = completion_name.into(); | 321 | let completion_name = completion_name.into(); |
322 | 322 | ctx.expected_name.as_ref().map_or(false, |name| name.text() == completion_name) | |
323 | Some(&completion_name) == ctx.expected_name.as_ref() | ||
324 | } | 323 | } |
325 | 324 | ||
326 | fn compute_ref_match(ctx: &CompletionContext, completion_ty: &hir::Type) -> Option<Mutability> { | 325 | fn compute_ref_match(ctx: &CompletionContext, completion_ty: &hir::Type) -> Option<Mutability> { |
diff --git a/crates/ide_db/src/call_info.rs b/crates/ide_db/src/call_info.rs index 7e26c3ccf..e583a52f4 100644 --- a/crates/ide_db/src/call_info.rs +++ b/crates/ide_db/src/call_info.rs | |||
@@ -4,7 +4,7 @@ use either::Either; | |||
4 | use hir::{HasAttrs, HirDisplay, Semantics, Type}; | 4 | use hir::{HasAttrs, HirDisplay, Semantics, Type}; |
5 | use stdx::format_to; | 5 | use stdx::format_to; |
6 | use syntax::{ | 6 | use syntax::{ |
7 | ast::{self, ArgListOwner}, | 7 | ast::{self, ArgListOwner, NameOwner}, |
8 | match_ast, AstNode, SyntaxNode, SyntaxToken, TextRange, TextSize, | 8 | match_ast, AstNode, SyntaxNode, SyntaxToken, TextRange, TextSize, |
9 | }; | 9 | }; |
10 | 10 | ||
@@ -142,7 +142,7 @@ fn call_info_impl( | |||
142 | #[derive(Debug)] | 142 | #[derive(Debug)] |
143 | pub struct ActiveParameter { | 143 | pub struct ActiveParameter { |
144 | pub ty: Type, | 144 | pub ty: Type, |
145 | pub name: String, | 145 | pub pat: Either<ast::SelfParam, ast::Pat>, |
146 | } | 146 | } |
147 | 147 | ||
148 | impl ActiveParameter { | 148 | impl ActiveParameter { |
@@ -165,8 +165,14 @@ impl ActiveParameter { | |||
165 | return None; | 165 | return None; |
166 | } | 166 | } |
167 | let (pat, ty) = params.swap_remove(idx); | 167 | let (pat, ty) = params.swap_remove(idx); |
168 | let name = pat?.to_string(); | 168 | pat.map(|pat| ActiveParameter { ty, pat }) |
169 | Some(ActiveParameter { ty, name }) | 169 | } |
170 | |||
171 | pub fn ident(&self) -> Option<ast::Name> { | ||
172 | self.pat.as_ref().right().and_then(|param| match param { | ||
173 | ast::Pat::IdentPat(ident) => ident.name(), | ||
174 | _ => None, | ||
175 | }) | ||
170 | } | 176 | } |
171 | } | 177 | } |
172 | 178 | ||
diff --git a/crates/syntax/src/ast/node_ext.rs b/crates/syntax/src/ast/node_ext.rs index 01f580a40..42a7b9c2a 100644 --- a/crates/syntax/src/ast/node_ext.rs +++ b/crates/syntax/src/ast/node_ext.rs | |||
@@ -380,6 +380,15 @@ impl fmt::Display for NameOrNameRef { | |||
380 | } | 380 | } |
381 | } | 381 | } |
382 | 382 | ||
383 | impl NameOrNameRef { | ||
384 | pub fn text(&self) -> &str { | ||
385 | match self { | ||
386 | NameOrNameRef::Name(name) => name.text(), | ||
387 | NameOrNameRef::NameRef(name_ref) => name_ref.text(), | ||
388 | } | ||
389 | } | ||
390 | } | ||
391 | |||
383 | impl ast::RecordPatField { | 392 | impl ast::RecordPatField { |
384 | pub fn for_field_name_ref(field_name: &ast::NameRef) -> Option<ast::RecordPatField> { | 393 | pub fn for_field_name_ref(field_name: &ast::NameRef) -> Option<ast::RecordPatField> { |
385 | let candidate = field_name.syntax().parent().and_then(ast::RecordPatField::cast)?; | 394 | let candidate = field_name.syntax().parent().and_then(ast::RecordPatField::cast)?; |