diff options
Diffstat (limited to 'crates/ide_completion')
-rw-r--r-- | crates/ide_completion/Cargo.toml | 2 | ||||
-rw-r--r-- | crates/ide_completion/src/completions.rs | 10 | ||||
-rw-r--r-- | crates/ide_completion/src/completions/dot.rs | 2 | ||||
-rw-r--r-- | crates/ide_completion/src/completions/flyimport.rs | 18 | ||||
-rw-r--r-- | crates/ide_completion/src/completions/postfix.rs | 20 | ||||
-rw-r--r-- | crates/ide_completion/src/completions/postfix/format_like.rs | 4 | ||||
-rw-r--r-- | crates/ide_completion/src/completions/qualified_path.rs | 2 | ||||
-rw-r--r-- | crates/ide_completion/src/completions/unqualified_path.rs | 34 | ||||
-rw-r--r-- | crates/ide_completion/src/context.rs | 4 | ||||
-rw-r--r-- | crates/ide_completion/src/patterns.rs | 19 | ||||
-rw-r--r-- | crates/ide_completion/src/render.rs | 21 | ||||
-rw-r--r-- | crates/ide_completion/src/render/function.rs | 26 | ||||
-rw-r--r-- | crates/ide_completion/src/render/pattern.rs | 6 | ||||
-rw-r--r-- | crates/ide_completion/src/render/type_alias.rs | 23 |
14 files changed, 126 insertions, 65 deletions
diff --git a/crates/ide_completion/Cargo.toml b/crates/ide_completion/Cargo.toml index ba81c9e04..3c45fe1cb 100644 --- a/crates/ide_completion/Cargo.toml +++ b/crates/ide_completion/Cargo.toml | |||
@@ -10,7 +10,7 @@ edition = "2018" | |||
10 | doctest = false | 10 | doctest = false |
11 | 11 | ||
12 | [dependencies] | 12 | [dependencies] |
13 | cov-mark = { version = "1.1", features = ["thread-local"] } | 13 | cov-mark = "2.0.0-pre.1" |
14 | itertools = "0.10.0" | 14 | itertools = "0.10.0" |
15 | log = "0.4.8" | 15 | log = "0.4.8" |
16 | rustc-hash = "1.1.0" | 16 | rustc-hash = "1.1.0" |
diff --git a/crates/ide_completion/src/completions.rs b/crates/ide_completion/src/completions.rs index fbd499900..bd90cefb2 100644 --- a/crates/ide_completion/src/completions.rs +++ b/crates/ide_completion/src/completions.rs | |||
@@ -29,7 +29,7 @@ use crate::{ | |||
29 | macro_::render_macro, | 29 | macro_::render_macro, |
30 | pattern::{render_struct_pat, render_variant_pat}, | 30 | pattern::{render_struct_pat, render_variant_pat}, |
31 | render_field, render_resolution, render_tuple_field, | 31 | render_field, render_resolution, render_tuple_field, |
32 | type_alias::render_type_alias, | 32 | type_alias::{render_type_alias, render_type_alias_with_eq}, |
33 | RenderContext, | 33 | RenderContext, |
34 | }, | 34 | }, |
35 | CompletionContext, CompletionItem, CompletionItemKind, | 35 | CompletionContext, CompletionItem, CompletionItemKind, |
@@ -188,6 +188,14 @@ impl Completions { | |||
188 | self.add_opt(render_type_alias(RenderContext::new(ctx), type_alias)); | 188 | self.add_opt(render_type_alias(RenderContext::new(ctx), type_alias)); |
189 | } | 189 | } |
190 | 190 | ||
191 | pub(crate) fn add_type_alias_with_eq( | ||
192 | &mut self, | ||
193 | ctx: &CompletionContext, | ||
194 | type_alias: hir::TypeAlias, | ||
195 | ) { | ||
196 | self.add_opt(render_type_alias_with_eq(RenderContext::new(ctx), type_alias)); | ||
197 | } | ||
198 | |||
191 | pub(crate) fn add_qualified_enum_variant( | 199 | pub(crate) fn add_qualified_enum_variant( |
192 | &mut self, | 200 | &mut self, |
193 | ctx: &CompletionContext, | 201 | ctx: &CompletionContext, |
diff --git a/crates/ide_completion/src/completions/dot.rs b/crates/ide_completion/src/completions/dot.rs index 8ad57a069..9552875c1 100644 --- a/crates/ide_completion/src/completions/dot.rs +++ b/crates/ide_completion/src/completions/dot.rs | |||
@@ -13,7 +13,7 @@ pub(crate) fn complete_dot(acc: &mut Completions, ctx: &CompletionContext) { | |||
13 | _ => return complete_undotted_self(acc, ctx), | 13 | _ => return complete_undotted_self(acc, ctx), |
14 | }; | 14 | }; |
15 | 15 | ||
16 | let receiver_ty = match ctx.sema.type_of_expr(&dot_receiver) { | 16 | let receiver_ty = match ctx.sema.type_of_expr(dot_receiver) { |
17 | Some(ty) => ty, | 17 | Some(ty) => ty, |
18 | _ => return, | 18 | _ => return, |
19 | }; | 19 | }; |
diff --git a/crates/ide_completion/src/completions/flyimport.rs b/crates/ide_completion/src/completions/flyimport.rs index c010cbbca..30b8d44bd 100644 --- a/crates/ide_completion/src/completions/flyimport.rs +++ b/crates/ide_completion/src/completions/flyimport.rs | |||
@@ -1,10 +1,10 @@ | |||
1 | //! Feature: completion with imports-on-the-fly | 1 | //! Feature: completion with imports-on-the-fly |
2 | //! | 2 | //! |
3 | //! When completing names in the current scope, proposes additional imports from other modules or crates, | 3 | //! When completing names in the current scope, proposes additional imports from other modules or crates, |
4 | //! if they can be qualified in the scope and their name contains all symbols from the completion input. | 4 | //! if they can be qualified in the scope, and their name contains all symbols from the completion input. |
5 | //! | 5 | //! |
6 | //! To be considered applicable, the name must contain all input symbols in the given order, not necessarily adjacent. | 6 | //! To be considered applicable, the name must contain all input symbols in the given order, not necessarily adjacent. |
7 | //! If any input symbol is not lowercased, the name must contain all symbols in exact case; otherwise the contaning is checked case-insensitively. | 7 | //! If any input symbol is not lowercased, the name must contain all symbols in exact case; otherwise the containing is checked case-insensitively. |
8 | //! | 8 | //! |
9 | //! ``` | 9 | //! ``` |
10 | //! fn main() { | 10 | //! fn main() { |
@@ -23,8 +23,8 @@ | |||
23 | //! ``` | 23 | //! ``` |
24 | //! | 24 | //! |
25 | //! Also completes associated items, that require trait imports. | 25 | //! Also completes associated items, that require trait imports. |
26 | //! If any unresolved and/or partially-qualified path predeces the input, it will be taken into account. | 26 | //! If any unresolved and/or partially-qualified path precedes the input, it will be taken into account. |
27 | //! Currently, only the imports with their import path ending with the whole qialifier will be proposed | 27 | //! Currently, only the imports with their import path ending with the whole qualifier will be proposed |
28 | //! (no fuzzy matching for qualifier). | 28 | //! (no fuzzy matching for qualifier). |
29 | //! | 29 | //! |
30 | //! ``` | 30 | //! ``` |
@@ -61,14 +61,14 @@ | |||
61 | //! } | 61 | //! } |
62 | //! ``` | 62 | //! ``` |
63 | //! | 63 | //! |
64 | //! NOTE: currently, if an assoc item comes from a trait that's not currently imported and it also has an unresolved and/or partially-qualified path, | 64 | //! NOTE: currently, if an assoc item comes from a trait that's not currently imported, and it also has an unresolved and/or partially-qualified path, |
65 | //! no imports will be proposed. | 65 | //! no imports will be proposed. |
66 | //! | 66 | //! |
67 | //! .Fuzzy search details | 67 | //! .Fuzzy search details |
68 | //! | 68 | //! |
69 | //! To avoid an excessive amount of the results returned, completion input is checked for inclusion in the names only | 69 | //! To avoid an excessive amount of the results returned, completion input is checked for inclusion in the names only |
70 | //! (i.e. in `HashMap` in the `std::collections::HashMap` path). | 70 | //! (i.e. in `HashMap` in the `std::collections::HashMap` path). |
71 | //! For the same reasons, avoids searching for any path imports for inputs with their length less that 2 symbols | 71 | //! For the same reasons, avoids searching for any path imports for inputs with their length less than 2 symbols |
72 | //! (but shows all associated items for any input length). | 72 | //! (but shows all associated items for any input length). |
73 | //! | 73 | //! |
74 | //! .Import configuration | 74 | //! .Import configuration |
@@ -79,15 +79,15 @@ | |||
79 | //! .LSP and performance implications | 79 | //! .LSP and performance implications |
80 | //! | 80 | //! |
81 | //! The feature is enabled only if the LSP client supports LSP protocol version 3.16+ and reports the `additionalTextEdits` | 81 | //! The feature is enabled only if the LSP client supports LSP protocol version 3.16+ and reports the `additionalTextEdits` |
82 | //! (case sensitive) resolve client capability in its client capabilities. | 82 | //! (case-sensitive) resolve client capability in its client capabilities. |
83 | //! This way the server is able to defer the costly computations, doing them for a selected completion item only. | 83 | //! This way the server is able to defer the costly computations, doing them for a selected completion item only. |
84 | //! For clients with no such support, all edits have to be calculated on the completion request, including the fuzzy search completion ones, | 84 | //! For clients with no such support, all edits have to be calculated on the completion request, including the fuzzy search completion ones, |
85 | //! which might be slow ergo the feature is automatically disabled. | 85 | //! which might be slow ergo the feature is automatically disabled. |
86 | //! | 86 | //! |
87 | //! .Feature toggle | 87 | //! .Feature toggle |
88 | //! | 88 | //! |
89 | //! The feature can be forcefully turned off in the settings with the `rust-analyzer.completion.enableAutoimportCompletions` flag. | 89 | //! The feature can be forcefully turned off in the settings with the `rust-analyzer.completion.autoimport.enable` flag. |
90 | //! Note that having this flag set to `true` does not guarantee that the feature is enabled: your client needs to have the corredponding | 90 | //! Note that having this flag set to `true` does not guarantee that the feature is enabled: your client needs to have the corresponding |
91 | //! capability enabled. | 91 | //! capability enabled. |
92 | 92 | ||
93 | use ide_db::helpers::{ | 93 | use ide_db::helpers::{ |
diff --git a/crates/ide_completion/src/completions/postfix.rs b/crates/ide_completion/src/completions/postfix.rs index 86eb21714..9f98b21be 100644 --- a/crates/ide_completion/src/completions/postfix.rs +++ b/crates/ide_completion/src/completions/postfix.rs | |||
@@ -34,7 +34,7 @@ pub(crate) fn complete_postfix(acc: &mut Completions, ctx: &CompletionContext) { | |||
34 | 34 | ||
35 | let receiver_text = get_receiver_text(dot_receiver, receiver_is_ambiguous_float_literal); | 35 | let receiver_text = get_receiver_text(dot_receiver, receiver_is_ambiguous_float_literal); |
36 | 36 | ||
37 | let receiver_ty = match ctx.sema.type_of_expr(&dot_receiver) { | 37 | let receiver_ty = match ctx.sema.type_of_expr(dot_receiver) { |
38 | Some(it) => it, | 38 | Some(it) => it, |
39 | None => return, | 39 | None => return, |
40 | }; | 40 | }; |
@@ -50,7 +50,7 @@ pub(crate) fn complete_postfix(acc: &mut Completions, ctx: &CompletionContext) { | |||
50 | postfix_snippet( | 50 | postfix_snippet( |
51 | ctx, | 51 | ctx, |
52 | cap, | 52 | cap, |
53 | &dot_receiver, | 53 | dot_receiver, |
54 | "ifl", | 54 | "ifl", |
55 | "if let Ok {}", | 55 | "if let Ok {}", |
56 | &format!("if let Ok($1) = {} {{\n $0\n}}", receiver_text), | 56 | &format!("if let Ok($1) = {} {{\n $0\n}}", receiver_text), |
@@ -60,7 +60,7 @@ pub(crate) fn complete_postfix(acc: &mut Completions, ctx: &CompletionContext) { | |||
60 | postfix_snippet( | 60 | postfix_snippet( |
61 | ctx, | 61 | ctx, |
62 | cap, | 62 | cap, |
63 | &dot_receiver, | 63 | dot_receiver, |
64 | "while", | 64 | "while", |
65 | "while let Ok {}", | 65 | "while let Ok {}", |
66 | &format!("while let Ok($1) = {} {{\n $0\n}}", receiver_text), | 66 | &format!("while let Ok($1) = {} {{\n $0\n}}", receiver_text), |
@@ -71,7 +71,7 @@ pub(crate) fn complete_postfix(acc: &mut Completions, ctx: &CompletionContext) { | |||
71 | postfix_snippet( | 71 | postfix_snippet( |
72 | ctx, | 72 | ctx, |
73 | cap, | 73 | cap, |
74 | &dot_receiver, | 74 | dot_receiver, |
75 | "ifl", | 75 | "ifl", |
76 | "if let Some {}", | 76 | "if let Some {}", |
77 | &format!("if let Some($1) = {} {{\n $0\n}}", receiver_text), | 77 | &format!("if let Some($1) = {} {{\n $0\n}}", receiver_text), |
@@ -81,7 +81,7 @@ pub(crate) fn complete_postfix(acc: &mut Completions, ctx: &CompletionContext) { | |||
81 | postfix_snippet( | 81 | postfix_snippet( |
82 | ctx, | 82 | ctx, |
83 | cap, | 83 | cap, |
84 | &dot_receiver, | 84 | dot_receiver, |
85 | "while", | 85 | "while", |
86 | "while let Some {}", | 86 | "while let Some {}", |
87 | &format!("while let Some($1) = {} {{\n $0\n}}", receiver_text), | 87 | &format!("while let Some($1) = {} {{\n $0\n}}", receiver_text), |
@@ -93,7 +93,7 @@ pub(crate) fn complete_postfix(acc: &mut Completions, ctx: &CompletionContext) { | |||
93 | postfix_snippet( | 93 | postfix_snippet( |
94 | ctx, | 94 | ctx, |
95 | cap, | 95 | cap, |
96 | &dot_receiver, | 96 | dot_receiver, |
97 | "if", | 97 | "if", |
98 | "if expr {}", | 98 | "if expr {}", |
99 | &format!("if {} {{\n $0\n}}", receiver_text), | 99 | &format!("if {} {{\n $0\n}}", receiver_text), |
@@ -102,22 +102,22 @@ pub(crate) fn complete_postfix(acc: &mut Completions, ctx: &CompletionContext) { | |||
102 | postfix_snippet( | 102 | postfix_snippet( |
103 | ctx, | 103 | ctx, |
104 | cap, | 104 | cap, |
105 | &dot_receiver, | 105 | dot_receiver, |
106 | "while", | 106 | "while", |
107 | "while expr {}", | 107 | "while expr {}", |
108 | &format!("while {} {{\n $0\n}}", receiver_text), | 108 | &format!("while {} {{\n $0\n}}", receiver_text), |
109 | ) | 109 | ) |
110 | .add_to(acc); | 110 | .add_to(acc); |
111 | postfix_snippet(ctx, cap, &dot_receiver, "not", "!expr", &format!("!{}", receiver_text)) | 111 | postfix_snippet(ctx, cap, dot_receiver, "not", "!expr", &format!("!{}", receiver_text)) |
112 | .add_to(acc); | 112 | .add_to(acc); |
113 | } | 113 | } |
114 | 114 | ||
115 | postfix_snippet(ctx, cap, &dot_receiver, "ref", "&expr", &format!("&{}", receiver_text)) | 115 | postfix_snippet(ctx, cap, dot_receiver, "ref", "&expr", &format!("&{}", receiver_text)) |
116 | .add_to(acc); | 116 | .add_to(acc); |
117 | postfix_snippet( | 117 | postfix_snippet( |
118 | ctx, | 118 | ctx, |
119 | cap, | 119 | cap, |
120 | &dot_receiver, | 120 | dot_receiver, |
121 | "refm", | 121 | "refm", |
122 | "&mut expr", | 122 | "&mut expr", |
123 | &format!("&mut {}", receiver_text), | 123 | &format!("&mut {}", receiver_text), |
diff --git a/crates/ide_completion/src/completions/postfix/format_like.rs b/crates/ide_completion/src/completions/postfix/format_like.rs index 9ebe1dcc0..2dc13c293 100644 --- a/crates/ide_completion/src/completions/postfix/format_like.rs +++ b/crates/ide_completion/src/completions/postfix/format_like.rs | |||
@@ -53,7 +53,7 @@ pub(crate) fn add_format_like_completions( | |||
53 | for (label, macro_name) in KINDS { | 53 | for (label, macro_name) in KINDS { |
54 | let snippet = parser.into_suggestion(macro_name); | 54 | let snippet = parser.into_suggestion(macro_name); |
55 | 55 | ||
56 | postfix_snippet(ctx, cap, &dot_receiver, label, macro_name, &snippet).add_to(acc); | 56 | postfix_snippet(ctx, cap, dot_receiver, label, macro_name, &snippet).add_to(acc); |
57 | } | 57 | } |
58 | } | 58 | } |
59 | } | 59 | } |
@@ -91,7 +91,7 @@ enum State { | |||
91 | impl FormatStrParser { | 91 | impl FormatStrParser { |
92 | pub(crate) fn new(input: String) -> Self { | 92 | pub(crate) fn new(input: String) -> Self { |
93 | Self { | 93 | Self { |
94 | input: input, | 94 | input, |
95 | output: String::new(), | 95 | output: String::new(), |
96 | extracted_expressions: Vec::new(), | 96 | extracted_expressions: Vec::new(), |
97 | state: State::NotExpr, | 97 | state: State::NotExpr, |
diff --git a/crates/ide_completion/src/completions/qualified_path.rs b/crates/ide_completion/src/completions/qualified_path.rs index 58d4dd9ee..6083537b7 100644 --- a/crates/ide_completion/src/completions/qualified_path.rs +++ b/crates/ide_completion/src/completions/qualified_path.rs | |||
@@ -15,7 +15,7 @@ pub(crate) fn complete_qualified_path(acc: &mut Completions, ctx: &CompletionCon | |||
15 | None => return, | 15 | None => return, |
16 | }; | 16 | }; |
17 | 17 | ||
18 | let resolution = match ctx.sema.resolve_path(&path) { | 18 | let resolution = match ctx.sema.resolve_path(path) { |
19 | Some(res) => res, | 19 | Some(res) => res, |
20 | None => return, | 20 | None => return, |
21 | }; | 21 | }; |
diff --git a/crates/ide_completion/src/completions/unqualified_path.rs b/crates/ide_completion/src/completions/unqualified_path.rs index b1e6b2b77..952f052a1 100644 --- a/crates/ide_completion/src/completions/unqualified_path.rs +++ b/crates/ide_completion/src/completions/unqualified_path.rs | |||
@@ -1,8 +1,9 @@ | |||
1 | //! Completion of names from the current scope, e.g. locals and imported items. | 1 | //! Completion of names from the current scope, e.g. locals and imported items. |
2 | 2 | ||
3 | use hir::ScopeDef; | 3 | use hir::ScopeDef; |
4 | use syntax::{ast, AstNode}; | ||
4 | 5 | ||
5 | use crate::{CompletionContext, Completions}; | 6 | use crate::{patterns::ImmediateLocation, CompletionContext, Completions}; |
6 | 7 | ||
7 | pub(crate) fn complete_unqualified_path(acc: &mut Completions, ctx: &CompletionContext) { | 8 | pub(crate) fn complete_unqualified_path(acc: &mut Completions, ctx: &CompletionContext) { |
8 | if ctx.is_path_disallowed() || !ctx.is_trivial_path() { | 9 | if ctx.is_path_disallowed() || !ctx.is_trivial_path() { |
@@ -43,6 +44,20 @@ pub(crate) fn complete_unqualified_path(acc: &mut Completions, ctx: &CompletionC | |||
43 | }); | 44 | }); |
44 | } | 45 | } |
45 | 46 | ||
47 | if let Some(ImmediateLocation::GenericArgList(arg_list)) = &ctx.completion_location { | ||
48 | if let Some(path_seg) = arg_list.syntax().parent().and_then(ast::PathSegment::cast) { | ||
49 | if let Some(hir::PathResolution::Def(hir::ModuleDef::Trait(trait_))) = | ||
50 | ctx.sema.resolve_path(&path_seg.parent_path()) | ||
51 | { | ||
52 | trait_.items(ctx.sema.db).into_iter().for_each(|it| { | ||
53 | if let hir::AssocItem::TypeAlias(alias) = it { | ||
54 | acc.add_type_alias_with_eq(ctx, alias) | ||
55 | } | ||
56 | }); | ||
57 | } | ||
58 | } | ||
59 | } | ||
60 | |||
46 | ctx.scope.process_all_names(&mut |name, res| { | 61 | ctx.scope.process_all_names(&mut |name, res| { |
47 | if let ScopeDef::GenericParam(hir::GenericParam::LifetimeParam(_)) = res { | 62 | if let ScopeDef::GenericParam(hir::GenericParam::LifetimeParam(_)) = res { |
48 | cov_mark::hit!(skip_lifetime_completion); | 63 | cov_mark::hit!(skip_lifetime_completion); |
@@ -777,4 +792,21 @@ $0 | |||
777 | "#]], | 792 | "#]], |
778 | ) | 793 | ) |
779 | } | 794 | } |
795 | |||
796 | #[test] | ||
797 | fn completes_assoc_types_in_dynimpl_trait() { | ||
798 | check( | ||
799 | r#" | ||
800 | trait Foo { | ||
801 | type Bar; | ||
802 | } | ||
803 | |||
804 | fn foo(_: impl Foo<B$0>) {} | ||
805 | "#, | ||
806 | expect![[r#" | ||
807 | ta Bar = type Bar; | ||
808 | tt Foo | ||
809 | "#]], | ||
810 | ); | ||
811 | } | ||
780 | } | 812 | } |
diff --git a/crates/ide_completion/src/context.rs b/crates/ide_completion/src/context.rs index 2c2a4aa6b..4c3929a26 100644 --- a/crates/ide_completion/src/context.rs +++ b/crates/ide_completion/src/context.rs | |||
@@ -380,7 +380,7 @@ impl<'a> CompletionContext<'a> { | |||
380 | (|| { | 380 | (|| { |
381 | let expr_field = self.token.prev_sibling_or_token()? | 381 | let expr_field = self.token.prev_sibling_or_token()? |
382 | .into_node() | 382 | .into_node() |
383 | .and_then(|node| ast::RecordExprField::cast(node))?; | 383 | .and_then(ast::RecordExprField::cast)?; |
384 | let (_, _, ty) = self.sema.resolve_record_field(&expr_field)?; | 384 | let (_, _, ty) = self.sema.resolve_record_field(&expr_field)?; |
385 | Some(( | 385 | Some(( |
386 | Some(ty), | 386 | Some(ty), |
@@ -467,7 +467,7 @@ impl<'a> CompletionContext<'a> { | |||
467 | self.expected_type = expected_type; | 467 | self.expected_type = expected_type; |
468 | self.expected_name = expected_name; | 468 | self.expected_name = expected_name; |
469 | 469 | ||
470 | let name_like = match find_node_at_offset(&&file_with_fake_ident, offset) { | 470 | let name_like = match find_node_at_offset(&file_with_fake_ident, offset) { |
471 | Some(it) => it, | 471 | Some(it) => it, |
472 | None => return, | 472 | None => return, |
473 | }; | 473 | }; |
diff --git a/crates/ide_completion/src/patterns.rs b/crates/ide_completion/src/patterns.rs index ee87bf461..72e67e3c4 100644 --- a/crates/ide_completion/src/patterns.rs +++ b/crates/ide_completion/src/patterns.rs | |||
@@ -47,6 +47,9 @@ pub(crate) enum ImmediateLocation { | |||
47 | receiver_is_ambiguous_float_literal: bool, | 47 | receiver_is_ambiguous_float_literal: bool, |
48 | }, | 48 | }, |
49 | // Original file ast node | 49 | // Original file ast node |
50 | // Only set from a type arg | ||
51 | GenericArgList(ast::GenericArgList), | ||
52 | // Original file ast node | ||
50 | /// The record expr of the field name we are completing | 53 | /// The record expr of the field name we are completing |
51 | RecordExpr(ast::RecordExpr), | 54 | RecordExpr(ast::RecordExpr), |
52 | // Original file ast node | 55 | // Original file ast node |
@@ -112,12 +115,12 @@ pub(crate) fn determine_location( | |||
112 | ) -> Option<ImmediateLocation> { | 115 | ) -> Option<ImmediateLocation> { |
113 | let node = match name_like { | 116 | let node = match name_like { |
114 | ast::NameLike::NameRef(name_ref) => { | 117 | ast::NameLike::NameRef(name_ref) => { |
115 | if ast::RecordExprField::for_field_name(&name_ref).is_some() { | 118 | if ast::RecordExprField::for_field_name(name_ref).is_some() { |
116 | return sema | 119 | return sema |
117 | .find_node_at_offset_with_macros(original_file, offset) | 120 | .find_node_at_offset_with_macros(original_file, offset) |
118 | .map(ImmediateLocation::RecordExpr); | 121 | .map(ImmediateLocation::RecordExpr); |
119 | } | 122 | } |
120 | if ast::RecordPatField::for_field_name_ref(&name_ref).is_some() { | 123 | if ast::RecordPatField::for_field_name_ref(name_ref).is_some() { |
121 | return sema | 124 | return sema |
122 | .find_node_at_offset_with_macros(original_file, offset) | 125 | .find_node_at_offset_with_macros(original_file, offset) |
123 | .map(ImmediateLocation::RecordPat); | 126 | .map(ImmediateLocation::RecordPat); |
@@ -125,7 +128,7 @@ pub(crate) fn determine_location( | |||
125 | maximize_name_ref(name_ref) | 128 | maximize_name_ref(name_ref) |
126 | } | 129 | } |
127 | ast::NameLike::Name(name) => { | 130 | ast::NameLike::Name(name) => { |
128 | if ast::RecordPatField::for_field_name(&name).is_some() { | 131 | if ast::RecordPatField::for_field_name(name).is_some() { |
129 | return sema | 132 | return sema |
130 | .find_node_at_offset_with_macros(original_file, offset) | 133 | .find_node_at_offset_with_macros(original_file, offset) |
131 | .map(ImmediateLocation::RecordPat); | 134 | .map(ImmediateLocation::RecordPat); |
@@ -159,7 +162,6 @@ pub(crate) fn determine_location( | |||
159 | } | 162 | } |
160 | } | 163 | } |
161 | }; | 164 | }; |
162 | |||
163 | let res = match_ast! { | 165 | let res = match_ast! { |
164 | match parent { | 166 | match parent { |
165 | ast::IdentPat(_it) => ImmediateLocation::IdentPat, | 167 | ast::IdentPat(_it) => ImmediateLocation::IdentPat, |
@@ -174,6 +176,9 @@ pub(crate) fn determine_location( | |||
174 | Some(TRAIT) => ImmediateLocation::Trait, | 176 | Some(TRAIT) => ImmediateLocation::Trait, |
175 | _ => return None, | 177 | _ => return None, |
176 | }, | 178 | }, |
179 | ast::GenericArgList(_it) => sema | ||
180 | .find_node_at_offset_with_macros(original_file, offset) | ||
181 | .map(ImmediateLocation::GenericArgList)?, | ||
177 | ast::Module(it) => { | 182 | ast::Module(it) => { |
178 | if it.item_list().is_none() { | 183 | if it.item_list().is_none() { |
179 | ImmediateLocation::ModDeclaration(it) | 184 | ImmediateLocation::ModDeclaration(it) |
@@ -254,7 +259,7 @@ fn test_inside_impl_trait_block() { | |||
254 | } | 259 | } |
255 | 260 | ||
256 | pub(crate) fn previous_token(element: SyntaxElement) -> Option<SyntaxToken> { | 261 | pub(crate) fn previous_token(element: SyntaxElement) -> Option<SyntaxToken> { |
257 | element.into_token().and_then(|it| previous_non_trivia_token(it)) | 262 | element.into_token().and_then(previous_non_trivia_token) |
258 | } | 263 | } |
259 | 264 | ||
260 | /// Check if the token previous to the previous one is `for`. | 265 | /// Check if the token previous to the previous one is `for`. |
@@ -262,8 +267,8 @@ pub(crate) fn previous_token(element: SyntaxElement) -> Option<SyntaxToken> { | |||
262 | pub(crate) fn for_is_prev2(element: SyntaxElement) -> bool { | 267 | pub(crate) fn for_is_prev2(element: SyntaxElement) -> bool { |
263 | element | 268 | element |
264 | .into_token() | 269 | .into_token() |
265 | .and_then(|it| previous_non_trivia_token(it)) | 270 | .and_then(previous_non_trivia_token) |
266 | .and_then(|it| previous_non_trivia_token(it)) | 271 | .and_then(previous_non_trivia_token) |
267 | .filter(|it| it.kind() == T![for]) | 272 | .filter(|it| it.kind() == T![for]) |
268 | .is_some() | 273 | .is_some() |
269 | } | 274 | } |
diff --git a/crates/ide_completion/src/render.rs b/crates/ide_completion/src/render.rs index 902df46ca..d8ca18c73 100644 --- a/crates/ide_completion/src/render.rs +++ b/crates/ide_completion/src/render.rs | |||
@@ -86,7 +86,7 @@ impl<'a> RenderContext<'a> { | |||
86 | } | 86 | } |
87 | 87 | ||
88 | fn db(&self) -> &'a RootDatabase { | 88 | fn db(&self) -> &'a RootDatabase { |
89 | &self.completion.db | 89 | self.completion.db |
90 | } | 90 | } |
91 | 91 | ||
92 | fn source_range(&self) -> TextRange { | 92 | fn source_range(&self) -> TextRange { |
@@ -111,7 +111,10 @@ impl<'a> RenderContext<'a> { | |||
111 | hir::AssocItem::TypeAlias(it) => self.is_deprecated(it), | 111 | hir::AssocItem::TypeAlias(it) => self.is_deprecated(it), |
112 | }; | 112 | }; |
113 | is_assoc_deprecated | 113 | is_assoc_deprecated |
114 | || assoc.containing_trait(db).map(|trait_| self.is_deprecated(trait_)).unwrap_or(false) | 114 | || assoc |
115 | .containing_trait_or_trait_impl(db) | ||
116 | .map(|trait_| self.is_deprecated(trait_)) | ||
117 | .unwrap_or(false) | ||
115 | } | 118 | } |
116 | 119 | ||
117 | fn docs(&self, node: impl HasAttrs) -> Option<hir::Documentation> { | 120 | fn docs(&self, node: impl HasAttrs) -> Option<hir::Documentation> { |
@@ -132,16 +135,17 @@ fn render_field_( | |||
132 | ctx.source_range(), | 135 | ctx.source_range(), |
133 | receiver.map_or_else(|| name.clone(), |receiver| format!("{}.{}", receiver, name)), | 136 | receiver.map_or_else(|| name.clone(), |receiver| format!("{}.{}", receiver, name)), |
134 | ); | 137 | ); |
135 | item.kind(SymbolKind::Field) | ||
136 | .detail(ty.display(ctx.db()).to_string()) | ||
137 | .set_documentation(field.docs(ctx.db())) | ||
138 | .set_deprecated(is_deprecated); | ||
139 | 138 | ||
140 | item.set_relevance(CompletionRelevance { | 139 | item.set_relevance(CompletionRelevance { |
141 | type_match: compute_type_match(ctx.completion, ty), | 140 | type_match: compute_type_match(ctx.completion, ty), |
142 | exact_name_match: compute_exact_name_match(ctx.completion, &name), | 141 | exact_name_match: compute_exact_name_match(ctx.completion, &name), |
143 | ..CompletionRelevance::default() | 142 | ..CompletionRelevance::default() |
144 | }); | 143 | }); |
144 | item.kind(SymbolKind::Field) | ||
145 | .detail(ty.display(ctx.db()).to_string()) | ||
146 | .set_documentation(field.docs(ctx.db())) | ||
147 | .set_deprecated(is_deprecated) | ||
148 | .lookup_by(name); | ||
145 | 149 | ||
146 | if let Some(_ref_match) = compute_ref_match(ctx.completion, ty) { | 150 | if let Some(_ref_match) = compute_ref_match(ctx.completion, ty) { |
147 | // FIXME | 151 | // FIXME |
@@ -164,7 +168,9 @@ fn render_tuple_field_( | |||
164 | receiver.map_or_else(|| field.to_string(), |receiver| format!("{}.{}", receiver, field)), | 168 | receiver.map_or_else(|| field.to_string(), |receiver| format!("{}.{}", receiver, field)), |
165 | ); | 169 | ); |
166 | 170 | ||
167 | item.kind(SymbolKind::Field).detail(ty.display(ctx.db()).to_string()); | 171 | item.kind(SymbolKind::Field) |
172 | .detail(ty.display(ctx.db()).to_string()) | ||
173 | .lookup_by(field.to_string()); | ||
168 | 174 | ||
169 | item.build() | 175 | item.build() |
170 | } | 176 | } |
@@ -1001,6 +1007,7 @@ fn go(world: &WorldSnapshot) { go(w$0) } | |||
1001 | 1007 | ||
1002 | #[test] | 1008 | #[test] |
1003 | fn too_many_arguments() { | 1009 | fn too_many_arguments() { |
1010 | cov_mark::check!(too_many_arguments); | ||
1004 | check_relevance( | 1011 | check_relevance( |
1005 | r#" | 1012 | r#" |
1006 | struct Foo; | 1013 | struct Foo; |
diff --git a/crates/ide_completion/src/render/function.rs b/crates/ide_completion/src/render/function.rs index 1abeed96d..1357b9f4a 100644 --- a/crates/ide_completion/src/render/function.rs +++ b/crates/ide_completion/src/render/function.rs | |||
@@ -58,29 +58,29 @@ impl<'a> FunctionRender<'a> { | |||
58 | Some(FunctionRender { ctx, name, receiver, func: fn_, ast_node, is_method }) | 58 | Some(FunctionRender { ctx, name, receiver, func: fn_, ast_node, is_method }) |
59 | } | 59 | } |
60 | 60 | ||
61 | fn render(mut self, import_to_add: Option<ImportEdit>) -> CompletionItem { | 61 | fn render(self, import_to_add: Option<ImportEdit>) -> CompletionItem { |
62 | let params = self.params(); | 62 | let params = self.params(); |
63 | if let Some(receiver) = &self.receiver { | 63 | let call = if let Some(receiver) = &self.receiver { |
64 | self.name = format!("{}.{}", receiver, &self.name) | 64 | format!("{}.{}", receiver, &self.name) |
65 | } | 65 | } else { |
66 | let mut item = CompletionItem::new( | 66 | self.name.clone() |
67 | CompletionKind::Reference, | 67 | }; |
68 | self.ctx.source_range(), | 68 | let mut item = |
69 | self.name.clone(), | 69 | CompletionItem::new(CompletionKind::Reference, self.ctx.source_range(), call.clone()); |
70 | ); | ||
71 | item.kind(self.kind()) | 70 | item.kind(self.kind()) |
72 | .set_documentation(self.ctx.docs(self.func)) | 71 | .set_documentation(self.ctx.docs(self.func)) |
73 | .set_deprecated( | 72 | .set_deprecated( |
74 | self.ctx.is_deprecated(self.func) || self.ctx.is_deprecated_assoc_item(self.func), | 73 | self.ctx.is_deprecated(self.func) || self.ctx.is_deprecated_assoc_item(self.func), |
75 | ) | 74 | ) |
76 | .detail(self.detail()) | 75 | .detail(self.detail()) |
77 | .add_call_parens(self.ctx.completion, self.name.clone(), params) | 76 | .add_call_parens(self.ctx.completion, call.clone(), params) |
78 | .add_import(import_to_add); | 77 | .add_import(import_to_add) |
78 | .lookup_by(self.name); | ||
79 | 79 | ||
80 | let ret_type = self.func.ret_type(self.ctx.db()); | 80 | let ret_type = self.func.ret_type(self.ctx.db()); |
81 | item.set_relevance(CompletionRelevance { | 81 | item.set_relevance(CompletionRelevance { |
82 | type_match: compute_type_match(self.ctx.completion, &ret_type), | 82 | type_match: compute_type_match(self.ctx.completion, &ret_type), |
83 | exact_name_match: compute_exact_name_match(self.ctx.completion, &self.name), | 83 | exact_name_match: compute_exact_name_match(self.ctx.completion, &call), |
84 | ..CompletionRelevance::default() | 84 | ..CompletionRelevance::default() |
85 | }); | 85 | }); |
86 | 86 | ||
@@ -263,7 +263,7 @@ fn bar(s: &S) { | |||
263 | ); | 263 | ); |
264 | 264 | ||
265 | check_edit( | 265 | check_edit( |
266 | "self.foo", | 266 | "foo", |
267 | r#" | 267 | r#" |
268 | struct S {} | 268 | struct S {} |
269 | impl S { | 269 | impl S { |
diff --git a/crates/ide_completion/src/render/pattern.rs b/crates/ide_completion/src/render/pattern.rs index b4e80f424..3717a0409 100644 --- a/crates/ide_completion/src/render/pattern.rs +++ b/crates/ide_completion/src/render/pattern.rs | |||
@@ -75,10 +75,10 @@ fn render_pat( | |||
75 | ) -> Option<String> { | 75 | ) -> Option<String> { |
76 | let mut pat = match kind { | 76 | let mut pat = match kind { |
77 | StructKind::Tuple if ctx.snippet_cap().is_some() => { | 77 | StructKind::Tuple if ctx.snippet_cap().is_some() => { |
78 | render_tuple_as_pat(&fields, &name, fields_omitted) | 78 | render_tuple_as_pat(fields, name, fields_omitted) |
79 | } | 79 | } |
80 | StructKind::Record => { | 80 | StructKind::Record => { |
81 | render_record_as_pat(ctx.db(), ctx.snippet_cap(), &fields, &name, fields_omitted) | 81 | render_record_as_pat(ctx.db(), ctx.snippet_cap(), fields, name, fields_omitted) |
82 | } | 82 | } |
83 | _ => return None, | 83 | _ => return None, |
84 | }; | 84 | }; |
@@ -86,7 +86,7 @@ fn render_pat( | |||
86 | if ctx.completion.is_param { | 86 | if ctx.completion.is_param { |
87 | pat.push(':'); | 87 | pat.push(':'); |
88 | pat.push(' '); | 88 | pat.push(' '); |
89 | pat.push_str(&name); | 89 | pat.push_str(name); |
90 | } | 90 | } |
91 | if ctx.snippet_cap().is_some() { | 91 | if ctx.snippet_cap().is_some() { |
92 | pat.push_str("$0"); | 92 | pat.push_str("$0"); |
diff --git a/crates/ide_completion/src/render/type_alias.rs b/crates/ide_completion/src/render/type_alias.rs index e47b4c745..e0234171a 100644 --- a/crates/ide_completion/src/render/type_alias.rs +++ b/crates/ide_completion/src/render/type_alias.rs | |||
@@ -16,7 +16,14 @@ pub(crate) fn render_type_alias<'a>( | |||
16 | ctx: RenderContext<'a>, | 16 | ctx: RenderContext<'a>, |
17 | type_alias: hir::TypeAlias, | 17 | type_alias: hir::TypeAlias, |
18 | ) -> Option<CompletionItem> { | 18 | ) -> Option<CompletionItem> { |
19 | TypeAliasRender::new(ctx, type_alias)?.render() | 19 | TypeAliasRender::new(ctx, type_alias)?.render(false) |
20 | } | ||
21 | |||
22 | pub(crate) fn render_type_alias_with_eq<'a>( | ||
23 | ctx: RenderContext<'a>, | ||
24 | type_alias: hir::TypeAlias, | ||
25 | ) -> Option<CompletionItem> { | ||
26 | TypeAliasRender::new(ctx, type_alias)?.render(true) | ||
20 | } | 27 | } |
21 | 28 | ||
22 | #[derive(Debug)] | 29 | #[derive(Debug)] |
@@ -32,8 +39,14 @@ impl<'a> TypeAliasRender<'a> { | |||
32 | Some(TypeAliasRender { ctx, type_alias, ast_node }) | 39 | Some(TypeAliasRender { ctx, type_alias, ast_node }) |
33 | } | 40 | } |
34 | 41 | ||
35 | fn render(self) -> Option<CompletionItem> { | 42 | fn render(self, with_eq: bool) -> Option<CompletionItem> { |
36 | let name = self.name()?; | 43 | let name = self.ast_node.name().map(|name| { |
44 | if with_eq { | ||
45 | format!("{} = ", name.text()) | ||
46 | } else { | ||
47 | name.text().to_string() | ||
48 | } | ||
49 | })?; | ||
37 | let detail = self.detail(); | 50 | let detail = self.detail(); |
38 | 51 | ||
39 | let mut item = | 52 | let mut item = |
@@ -49,10 +62,6 @@ impl<'a> TypeAliasRender<'a> { | |||
49 | Some(item.build()) | 62 | Some(item.build()) |
50 | } | 63 | } |
51 | 64 | ||
52 | fn name(&self) -> Option<String> { | ||
53 | self.ast_node.name().map(|name| name.text().to_string()) | ||
54 | } | ||
55 | |||
56 | fn detail(&self) -> String { | 65 | fn detail(&self) -> String { |
57 | type_label(&self.ast_node) | 66 | type_label(&self.ast_node) |
58 | } | 67 | } |