Unnamed repository; edit this file 'description' to name the repository.
Show only assoc type args in the correct arg pos
Hongxu Xu 2022-07-06
parent 441e659 · commit 0f2eba5
-rw-r--r--crates/hir/src/lib.rs17
-rw-r--r--crates/ide-completion/src/completions/type.rs18
-rw-r--r--crates/ide-completion/src/tests/type_pos.rs37
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<TypeOrConstParamData> {
+ 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<T>: 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<T> {
type Item;
};
-fn f(t: impl MyTrait<I$0
+fn f(t: impl MyTrait<u8,I$0
"#,
expect![[r#"
ta Item = (as MyTrait) type Item