From 0f2eba54db7a16d2790f621adec54daa3e829973 Mon Sep 17 00:00:00 2001 From: Hongxu Xu Date: Wed, 6 Jul 2022 22:58:27 +0800 Subject: [PATCH] Show only assoc type args in the correct arg pos --- crates/hir/src/lib.rs | 17 +++++++++ crates/ide-completion/src/completions/type.rs | 18 ++++++++- crates/ide-completion/src/tests/type_pos.rs | 37 ++++++++++++++++++- 3 files changed, 69 insertions(+), 3 deletions(-) diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index ef17f2a75e..38beb90b36 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs @@ -41,6 +41,7 @@ use hir_def::{ adt::{ReprKind, VariantData}, body::{BodyDiagnostic, SyntheticSyntax}, expr::{BindingAnnotation, LabelId, Pat, PatId}, + generics::{TypeOrConstParamData, TypeParamProvenance}, item_tree::ItemTreeNode, lang_item::LangItemTarget, nameres::{self, diagnostics::DefDiagnostic}, @@ -1707,6 +1708,22 @@ impl Trait { pub fn is_unsafe(&self, db: &dyn HirDatabase) -> bool { db.trait_data(self.id).is_unsafe } + + pub fn type_parameters(&self, db: &dyn HirDatabase) -> Vec { + db.generic_params(GenericDefId::from(self.id)) + .type_or_consts + .iter() + .filter(|(_, ty)| match ty { + TypeOrConstParamData::TypeParamData(ty) + if ty.provenance != TypeParamProvenance::TypeParamList => + { + false + } + _ => true, + }) + .map(|(_, ty)|ty.clone()) + .collect() + } } impl HasVisibility for Trait { diff --git a/crates/ide-completion/src/completions/type.rs b/crates/ide-completion/src/completions/type.rs index 352708df73..0167098da1 100644 --- a/crates/ide-completion/src/completions/type.rs +++ b/crates/ide-completion/src/completions/type.rs @@ -1,6 +1,7 @@ //! Completion of names from the current scope in type position. use hir::{HirDisplay, ScopeDef}; +use itertools::Itertools; use syntax::{ast, AstNode}; use crate::{ @@ -140,6 +141,18 @@ pub(crate) fn complete_type_path( return; } TypeLocation::GenericArgList(Some(arg_list)) => { + // the current token is in which generic arg + let arg_pos = if let Some((pos, _)) = + arg_list.generic_args().find_position(|arg| { + arg.syntax() + .descendants_with_tokens() + .any(|t| t.as_token() == Some(&ctx.original_token)) + }) { + pos + } else { + 0 + }; + match arg_list.generic_args().next() { Some(ast::GenericArg::AssocTypeArg(_)) => {} _ => { @@ -167,7 +180,10 @@ pub(crate) fn complete_type_path( acc.add_type_alias_with_eq(ctx, alias); } }); - return; // only AssocTypeArgs make sense + + if arg_pos >= trait_.type_parameters(ctx.sema.db).len() { + return; // only AssocTypeArgs make sense + } } } } diff --git a/crates/ide-completion/src/tests/type_pos.rs b/crates/ide-completion/src/tests/type_pos.rs index b30d4cceb8..175acab57f 100644 --- a/crates/ide-completion/src/tests/type_pos.rs +++ b/crates/ide-completion/src/tests/type_pos.rs @@ -386,6 +386,39 @@ fn foo<'lt, T: Trait2<$0>, const CONST_PARAM: usize>(_: T) {} ); check( r#" +trait Trait1 { + type Super; +} +trait Trait2: Trait1 { + type Foo; +} + +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( + r#" trait Trait2 { type Foo; } @@ -460,11 +493,11 @@ fn func(_: Enum::$0) {} fn completes_associated_type_only() { check( r#" -trait MyTrait { +trait MyTrait { type Item; }; -fn f(t: impl MyTrait