Skip to content

Commit 1b3e20f

Browse files
committed
handle more cases
1 parent f4038a6 commit 1b3e20f

File tree

3 files changed

+128
-98
lines changed

3 files changed

+128
-98
lines changed

crates/ide-completion/src/completions/type.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,7 @@ pub(crate) fn complete_type_path(
173173
});
174174
return;
175175
}
176-
TypeLocation::GenericArgList(Some((arg_list, generic_param))) => {
176+
TypeLocation::GenericArgList(Some((arg_list, _))) => {
177177
let in_assoc_type_arg = ctx
178178
.original_token
179179
.parent_ancestors()

crates/ide-completion/src/context/analysis.rs

Lines changed: 27 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -726,20 +726,30 @@ fn classify_name_ref(
726726
arg.syntax().parent().and_then(ast::GenericArgList::cast),
727727
)
728728
.map(|args| {
729-
// Determine the index of the parameter in the `GenericArgList`
730-
// (subtract 1 because `siblings` includes the node itself)
731-
let param_idx = arg.syntax().siblings(Direction::Prev).count() - 1;
732-
let parent = args.syntax().parent();
733-
let param = parent.and_then(|parent| {
734-
match_ast! {
729+
let param = (|| {
730+
let parent = args.syntax().parent()?;
731+
let params = match_ast! {
735732
match parent {
736733
ast::PathSegment(segment) => {
737734
match sema.resolve_path(&segment.parent_path().top_path())? {
738735
hir::PathResolution::Def(def) => match def {
739736
hir::ModuleDef::Function(func) => {
740-
let src = func.source(sema.db)?;
741-
let params = src.value.generic_param_list()?;
742-
params.generic_params().nth(param_idx)
737+
func.source(sema.db)?.value.generic_param_list()
738+
}
739+
hir::ModuleDef::Adt(adt) => {
740+
adt.source(sema.db)?.value.generic_param_list()
741+
}
742+
hir::ModuleDef::Variant(variant) => {
743+
variant.parent_enum(sema.db).source(sema.db)?.value.generic_param_list()
744+
}
745+
hir::ModuleDef::Trait(trait_) => {
746+
trait_.source(sema.db)?.value.generic_param_list()
747+
}
748+
hir::ModuleDef::TraitAlias(trait_) => {
749+
trait_.source(sema.db)?.value.generic_param_list()
750+
}
751+
hir::ModuleDef::TypeAlias(ty_) => {
752+
ty_.source(sema.db)?.value.generic_param_list()
743753
}
744754
_ => None,
745755
},
@@ -748,9 +758,7 @@ fn classify_name_ref(
748758
},
749759
ast::MethodCallExpr(call) => {
750760
let func = sema.resolve_method_call(&call)?;
751-
let src = func.source(sema.db)?;
752-
let params = src.value.generic_param_list()?;
753-
params.generic_params().nth(param_idx)
761+
func.source(sema.db)?.value.generic_param_list()
754762
},
755763
ast::AssocTypeArg(arg) => {
756764
let trait_ = ast::PathSegment::cast(arg.syntax().parent()?.parent()?)?;
@@ -765,9 +773,7 @@ fn classify_name_ref(
765773
},
766774
_ => None,
767775
})?;
768-
let src = assoc_ty.source(sema.db)?;
769-
let params = src.value.generic_param_list()?;
770-
params.generic_params().nth(param_idx)
776+
assoc_ty.source(sema.db)?.value.generic_param_list()
771777
}
772778
_ => None,
773779
},
@@ -776,8 +782,12 @@ fn classify_name_ref(
776782
},
777783
_ => None,
778784
}
779-
}
780-
});
785+
}?;
786+
// Determine the index of the parameter in the `GenericArgList`
787+
// (subtract 1 because `siblings` includes the node itself)
788+
let param_idx = arg.syntax().siblings(Direction::Prev).count() - 1;
789+
params.generic_params().nth(param_idx)
790+
})();
781791
(args, param)
782792
});
783793
TypeLocation::GenericArgList(location)

crates/ide-completion/src/tests/type_pos.rs

Lines changed: 100 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -722,16 +722,31 @@ pub struct S;
722722

723723
#[test]
724724
fn completes_const_and_type_generics_separately() {
725-
check(
725+
let type_completion_cases = [
726+
// Function
726727
r#"
727-
struct Foo;
728-
const X: usize = 0;
729-
fn foo<T, const N: usize>() {}
730-
fn main() {
731-
foo::<F$0, _>();
732-
}
733-
"#,
734-
expect![[r#"
728+
struct Foo;
729+
const X: usize = 0;
730+
fn foo<T, const N: usize>() {}
731+
fn main() {
732+
foo::<F$0, _>();
733+
}
734+
"#,
735+
// Method
736+
r#"
737+
const X: usize = 0;
738+
struct Foo;
739+
impl Foo { fn bar<const N: usize, T>(self) {} }
740+
fn main() {
741+
Foo.bar::<_, $0>();
742+
}
743+
"#,
744+
];
745+
746+
for case in type_completion_cases {
747+
check(
748+
case,
749+
expect![[r#"
735750
en Enum
736751
ma makro!(…) macro_rules! makro
737752
md module
@@ -745,51 +760,18 @@ fn completes_const_and_type_generics_separately() {
745760
kw crate::
746761
kw self::
747762
"#]],
748-
);
749-
check(
750-
r#"
751-
struct Foo;
752-
const X: usize = 0;
753-
fn foo<T, const N: usize>() {}
754-
fn main() {
755-
foo::<_, $0>();
763+
)
756764
}
757-
"#,
758-
expect![[r#"
759-
ct CONST
760-
ct X
761-
ma makro!(…) macro_rules! makro
762-
kw crate::
763-
kw self::
764-
"#]],
765-
);
766765

767766
check(
768767
r#"
769768
const X: usize = 0;
770769
struct Foo;
771-
impl Foo { fn bar<const N: usize, T>(self) {} }
772-
fn main() {
773-
Foo.bar::<X$0, _>();
774-
}
775-
"#,
776-
expect![[r#"
777-
ct CONST
778-
ct X
779-
ma makro!(…) macro_rules! makro
780-
kw crate::
781-
kw self::
782-
"#]],
783-
);
784-
check(
785-
r#"
786-
const X: usize = 0;
787-
struct Foo;
788-
impl Foo { fn bar<const N: usize, T>(self) {} }
789-
fn main() {
790-
Foo.bar::<_, $0>();
770+
trait Bar {
771+
type Baz<T, const X: usize>;
791772
}
792-
"#,
773+
fn foo(_: impl Bar<Baz<F$0, 0> = ()>) {}
774+
"#,
793775
expect![[r#"
794776
en Enum
795777
ma makro!(…) macro_rules! makro
@@ -798,6 +780,7 @@ fn main() {
798780
st Record
799781
st Tuple
800782
st Unit
783+
tt Bar
801784
tt Trait
802785
un Union
803786
bt u32
@@ -806,47 +789,84 @@ fn main() {
806789
"#]],
807790
);
808791

809-
check(
792+
let const_completion_cases = [
793+
// Function params
794+
r#"
795+
struct Foo;
796+
const X: usize = 0;
797+
fn foo<T, const N: usize>() {}
798+
fn main() {
799+
foo::<_, $0>();
800+
}
801+
"#,
802+
// Method params
810803
r#"
811804
const X: usize = 0;
812805
struct Foo;
813-
trait Bar {
814-
type Baz<T, const X: usize>;
806+
impl Foo { fn bar<const N: usize, T>(self) {} }
807+
fn main() {
808+
Foo.bar::<X$0, _>();
815809
}
816-
fn foo<T: Bar<Baz<(), $0> = ()>>() {}
817-
"#,
818-
expect![[r#"
819-
ct CONST
820-
ct X
821-
ma makro!(…) macro_rules! makro
822-
kw crate::
823-
kw self::
824-
"#]],
825-
);
826-
check(
810+
"#,
811+
// Associated type params
827812
r#"
828813
const X: usize = 0;
829814
struct Foo;
830815
trait Bar {
831816
type Baz<T, const X: usize>;
832817
}
833-
fn foo<T: Bar<Baz<F$0, 0> = ()>>() {}
834-
"#,
835-
expect![[r#"
836-
en Enum
837-
ma makro!(…) macro_rules! makro
838-
md module
839-
st Foo
840-
st Record
841-
st Tuple
842-
st Unit
843-
tt Bar
844-
tt Trait
845-
tp T
846-
un Union
847-
bt u32
848-
kw crate::
849-
kw self::
850-
"#]],
851-
);
818+
fn foo<T: Bar<Baz<(), $0> = ()>>() {}
819+
"#,
820+
// Type params
821+
r#"
822+
const X: usize = 0;
823+
struct Foo<T, const N: usize>(T);
824+
fn main() {
825+
let _: Foo::<_, $0> = todo!();
826+
}
827+
"#,
828+
// Enum variant params
829+
r#"
830+
const X: usize = 0;
831+
struct Foo<T, const N: usize>(T);
832+
type Bar<const X: usize, U> = Foo<U, X>;
833+
fn main() {
834+
let _: Bar::<X$0, _> = todo!();
835+
}
836+
"#,
837+
r#"
838+
const X: usize = 0;
839+
enum Foo<T, const N: usize> { A(T), B }
840+
fn main() {
841+
Foo::B::<(), $0>;
842+
}
843+
"#,
844+
// Trait params
845+
r#"
846+
const X: usize = 0;
847+
trait Foo<T, const N: usize> {}
848+
impl Foo<(), $0> for () {}
849+
"#,
850+
// Trait alias params
851+
r#"
852+
#![feature(trait_alias)]
853+
const X: usize = 0;
854+
trait Foo<T, const N: usize> {}
855+
trait Bar<const M: usize, U> = Foo<U, M>;
856+
fn foo<T: Bar<X$0, ()>>() {}
857+
"#,
858+
];
859+
860+
for case in const_completion_cases {
861+
check(
862+
case,
863+
expect![[r#"
864+
ct CONST
865+
ct X
866+
ma makro!(…) macro_rules! makro
867+
kw crate::
868+
kw self::
869+
"#]],
870+
);
871+
}
852872
}

0 commit comments

Comments
 (0)