Unnamed repository; edit this file 'description' to name the repository.
| -rw-r--r-- | crates/ide-completion/src/completions/type.rs | 83 | ||||
| -rw-r--r-- | crates/ide-completion/src/tests/type_pos.rs | 62 | ||||
| -rw-r--r-- | crates/rust-analyzer/tests/slow-tests/tidy.rs | 37 |
3 files changed, 119 insertions, 63 deletions
diff --git a/crates/ide-completion/src/completions/type.rs b/crates/ide-completion/src/completions/type.rs index 616d862154..352708df73 100644 --- a/crates/ide-completion/src/completions/type.rs +++ b/crates/ide-completion/src/completions/type.rs @@ -120,39 +120,64 @@ pub(crate) fn complete_type_path( } Qualified::Absolute => acc.add_crate_roots(ctx, path_ctx), Qualified::No => { - acc.add_nameref_keywords_with_colon(ctx); - if let TypeLocation::TypeBound = location { - ctx.process_all_names(&mut |name, res| { - let add_resolution = match res { - ScopeDef::ModuleDef(hir::ModuleDef::Macro(mac)) => mac.is_fn_like(ctx.db), - ScopeDef::ModuleDef( - hir::ModuleDef::Trait(_) | hir::ModuleDef::Module(_), - ) => true, - _ => false, - }; - if add_resolution { - acc.add_path_resolution(ctx, path_ctx, name, res); - } - }); - return; - } - if let TypeLocation::GenericArgList(Some(arg_list)) = location { - if let Some(path_seg) = arg_list.syntax().parent().and_then(ast::PathSegment::cast) - { - if path_seg.syntax().ancestors().find_map(ast::TypeBound::cast).is_some() { - if let Some(hir::PathResolution::Def(hir::ModuleDef::Trait(trait_))) = - ctx.sema.resolve_path(&path_seg.parent_path()) - { - trait_.items_with_supertraits(ctx.sema.db).into_iter().for_each(|it| { - if let hir::AssocItem::TypeAlias(alias) = it { - cov_mark::hit!(complete_assoc_type_in_generics_list); - acc.add_type_alias_with_eq(ctx, alias) + match location { + TypeLocation::TypeBound => { + acc.add_nameref_keywords_with_colon(ctx); + ctx.process_all_names(&mut |name, res| { + let add_resolution = match res { + ScopeDef::ModuleDef(hir::ModuleDef::Macro(mac)) => { + mac.is_fn_like(ctx.db) + } + ScopeDef::ModuleDef( + hir::ModuleDef::Trait(_) | hir::ModuleDef::Module(_), + ) => true, + _ => false, + }; + if add_resolution { + acc.add_path_resolution(ctx, path_ctx, name, res); + } + }); + return; + } + TypeLocation::GenericArgList(Some(arg_list)) => { + match arg_list.generic_args().next() { + Some(ast::GenericArg::AssocTypeArg(_)) => {} + _ => { + if let Some(path_seg) = + arg_list.syntax().parent().and_then(ast::PathSegment::cast) + { + if path_seg + .syntax() + .ancestors() + .find_map(ast::TypeBound::cast) + .is_some() + { + if let Some(hir::PathResolution::Def(hir::ModuleDef::Trait( + trait_, + ))) = ctx.sema.resolve_path(&path_seg.parent_path()) + { + trait_ + .items_with_supertraits(ctx.sema.db) + .into_iter() + .for_each(|it| { + if let hir::AssocItem::TypeAlias(alias) = it { + cov_mark::hit!( + complete_assoc_type_in_generics_list + ); + acc.add_type_alias_with_eq(ctx, alias); + } + }); + return; // only AssocTypeArgs make sense + } } - }); + } } } } - } + _ => {} + }; + + acc.add_nameref_keywords_with_colon(ctx); ctx.process_all_names(&mut |name, def| { if scope_def_applicable(def) { acc.add_path_resolution(ctx, path_ctx, name, def); diff --git a/crates/ide-completion/src/tests/type_pos.rs b/crates/ide-completion/src/tests/type_pos.rs index 8943d303b6..b30d4cceb8 100644 --- a/crates/ide-completion/src/tests/type_pos.rs +++ b/crates/ide-completion/src/tests/type_pos.rs @@ -380,25 +380,8 @@ trait Trait2: Trait1 { fn foo<'lt, T: Trait2<$0>, const CONST_PARAM: usize>(_: T) {} "#, expect![[r#" - ct CONST - cp CONST_PARAM - en Enum - ma makro!(…) macro_rules! makro - md module - st Record - st Tuple - st Unit - tt Trait - tt Trait1 - tt Trait2 ta Foo = (as Trait2) type Foo ta Super = (as Trait1) type Super - tp T - un Union - bt u32 - kw crate:: - kw self:: - kw super:: "#]], ); check( @@ -472,3 +455,48 @@ fn func(_: Enum::$0) {} "#]], ); } + +#[test] +fn completes_associated_type_only() { + check( + r#" +trait MyTrait { + type Item; +}; + +fn f(t: impl MyTrait<I$0 +"#, + expect![[r#" + ta Item = (as MyTrait) type Item + "#]], + ); +} + +#[test] +fn completes_types_after_associated_type() { + check( + r#" +trait MyTrait { + type Item; +}; + +fn f(t: impl MyTrait<Item = $0 +"#, + expect![[r#" + ct CONST + en Enum + ma makro!(…) macro_rules! makro + md module + st Record + st Tuple + st Unit + tt MyTrait + tt Trait + un Union + bt u32 + kw crate:: + kw self:: + kw super:: + "#]], + ); +} diff --git a/crates/rust-analyzer/tests/slow-tests/tidy.rs b/crates/rust-analyzer/tests/slow-tests/tidy.rs index 02ab608129..12be7947fe 100644 --- a/crates/rust-analyzer/tests/slow-tests/tidy.rs +++ b/crates/rust-analyzer/tests/slow-tests/tidy.rs @@ -471,17 +471,9 @@ struct TidyMarks { impl TidyMarks { fn visit(&mut self, _path: &Path, text: &str) { - for line in text.lines() { - if let Some(mark) = find_mark(line, "hit") { - self.hits.insert(mark.to_string()); - } - if let Some(mark) = find_mark(line, "check") { - self.checks.insert(mark.to_string()); - } - if let Some(mark) = find_mark(line, "check_count") { - self.checks.insert(mark.to_string()); - } - } + find_marks(&mut self.hits, text, "hit"); + find_marks(&mut self.checks, text, "check"); + find_marks(&mut self.checks, text, "check_count"); } fn finish(self) { @@ -506,10 +498,21 @@ fn stable_hash(text: &str) -> u64 { hasher.finish() } -fn find_mark<'a>(text: &'a str, mark: &'static str) -> Option<&'a str> { - let idx = text.find(mark)?; - let text = text[idx + mark.len()..].strip_prefix("!(")?; - let idx = text.find(|c: char| !(c.is_alphanumeric() || c == '_'))?; - let text = &text[..idx]; - Some(text) +fn find_marks(set: &mut HashSet<String>, text: &str, mark: &str) { + let mut text = text; + let mut prev_text = ""; + while text != prev_text { + prev_text = text; + if let Some(idx) = text.find(mark) { + text = &text[idx + mark.len()..]; + if let Some(stripped_text) = text.strip_prefix("!(") { + text = stripped_text.trim_start(); + if let Some(idx2) = text.find(|c: char| !(c.is_alphanumeric() || c == '_')) { + let mark_text = &text[..idx2]; + set.insert(mark_text.to_string()); + text = &text[idx2..]; + } + } + } + } } |