mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-09-27 20:42:04 +00:00
handle more cases
This commit is contained in:
parent
f4038a6bf1
commit
1b3e20fe68
3 changed files with 136 additions and 106 deletions
|
@ -173,7 +173,7 @@ pub(crate) fn complete_type_path(
|
|||
});
|
||||
return;
|
||||
}
|
||||
TypeLocation::GenericArgList(Some((arg_list, generic_param))) => {
|
||||
TypeLocation::GenericArgList(Some((arg_list, _))) => {
|
||||
let in_assoc_type_arg = ctx
|
||||
.original_token
|
||||
.parent_ancestors()
|
||||
|
|
|
@ -726,20 +726,30 @@ fn classify_name_ref(
|
|||
arg.syntax().parent().and_then(ast::GenericArgList::cast),
|
||||
)
|
||||
.map(|args| {
|
||||
// Determine the index of the parameter in the `GenericArgList`
|
||||
// (subtract 1 because `siblings` includes the node itself)
|
||||
let param_idx = arg.syntax().siblings(Direction::Prev).count() - 1;
|
||||
let parent = args.syntax().parent();
|
||||
let param = parent.and_then(|parent| {
|
||||
match_ast! {
|
||||
let param = (|| {
|
||||
let parent = args.syntax().parent()?;
|
||||
let params = match_ast! {
|
||||
match parent {
|
||||
ast::PathSegment(segment) => {
|
||||
match sema.resolve_path(&segment.parent_path().top_path())? {
|
||||
hir::PathResolution::Def(def) => match def {
|
||||
hir::ModuleDef::Function(func) => {
|
||||
let src = func.source(sema.db)?;
|
||||
let params = src.value.generic_param_list()?;
|
||||
params.generic_params().nth(param_idx)
|
||||
func.source(sema.db)?.value.generic_param_list()
|
||||
}
|
||||
hir::ModuleDef::Adt(adt) => {
|
||||
adt.source(sema.db)?.value.generic_param_list()
|
||||
}
|
||||
hir::ModuleDef::Variant(variant) => {
|
||||
variant.parent_enum(sema.db).source(sema.db)?.value.generic_param_list()
|
||||
}
|
||||
hir::ModuleDef::Trait(trait_) => {
|
||||
trait_.source(sema.db)?.value.generic_param_list()
|
||||
}
|
||||
hir::ModuleDef::TraitAlias(trait_) => {
|
||||
trait_.source(sema.db)?.value.generic_param_list()
|
||||
}
|
||||
hir::ModuleDef::TypeAlias(ty_) => {
|
||||
ty_.source(sema.db)?.value.generic_param_list()
|
||||
}
|
||||
_ => None,
|
||||
},
|
||||
|
@ -748,9 +758,7 @@ fn classify_name_ref(
|
|||
},
|
||||
ast::MethodCallExpr(call) => {
|
||||
let func = sema.resolve_method_call(&call)?;
|
||||
let src = func.source(sema.db)?;
|
||||
let params = src.value.generic_param_list()?;
|
||||
params.generic_params().nth(param_idx)
|
||||
func.source(sema.db)?.value.generic_param_list()
|
||||
},
|
||||
ast::AssocTypeArg(arg) => {
|
||||
let trait_ = ast::PathSegment::cast(arg.syntax().parent()?.parent()?)?;
|
||||
|
@ -765,19 +773,21 @@ fn classify_name_ref(
|
|||
},
|
||||
_ => None,
|
||||
})?;
|
||||
let src = assoc_ty.source(sema.db)?;
|
||||
let params = src.value.generic_param_list()?;
|
||||
assoc_ty.source(sema.db)?.value.generic_param_list()
|
||||
}
|
||||
_ => None,
|
||||
},
|
||||
_ => None,
|
||||
}
|
||||
},
|
||||
_ => None,
|
||||
}
|
||||
}?;
|
||||
// Determine the index of the parameter in the `GenericArgList`
|
||||
// (subtract 1 because `siblings` includes the node itself)
|
||||
let param_idx = arg.syntax().siblings(Direction::Prev).count() - 1;
|
||||
params.generic_params().nth(param_idx)
|
||||
}
|
||||
_ => None,
|
||||
},
|
||||
_ => None,
|
||||
}
|
||||
},
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
});
|
||||
})();
|
||||
(args, param)
|
||||
});
|
||||
TypeLocation::GenericArgList(location)
|
||||
|
|
|
@ -722,7 +722,8 @@ pub struct S;
|
|||
|
||||
#[test]
|
||||
fn completes_const_and_type_generics_separately() {
|
||||
check(
|
||||
let type_completion_cases = [
|
||||
// Function
|
||||
r#"
|
||||
struct Foo;
|
||||
const X: usize = 0;
|
||||
|
@ -731,57 +732,7 @@ fn completes_const_and_type_generics_separately() {
|
|||
foo::<F$0, _>();
|
||||
}
|
||||
"#,
|
||||
expect![[r#"
|
||||
en Enum
|
||||
ma makro!(…) macro_rules! makro
|
||||
md module
|
||||
st Foo
|
||||
st Record
|
||||
st Tuple
|
||||
st Unit
|
||||
tt Trait
|
||||
un Union
|
||||
bt u32
|
||||
kw crate::
|
||||
kw self::
|
||||
"#]],
|
||||
);
|
||||
check(
|
||||
r#"
|
||||
struct Foo;
|
||||
const X: usize = 0;
|
||||
fn foo<T, const N: usize>() {}
|
||||
fn main() {
|
||||
foo::<_, $0>();
|
||||
}
|
||||
"#,
|
||||
expect![[r#"
|
||||
ct CONST
|
||||
ct X
|
||||
ma makro!(…) macro_rules! makro
|
||||
kw crate::
|
||||
kw self::
|
||||
"#]],
|
||||
);
|
||||
|
||||
check(
|
||||
r#"
|
||||
const X: usize = 0;
|
||||
struct Foo;
|
||||
impl Foo { fn bar<const N: usize, T>(self) {} }
|
||||
fn main() {
|
||||
Foo.bar::<X$0, _>();
|
||||
}
|
||||
"#,
|
||||
expect![[r#"
|
||||
ct CONST
|
||||
ct X
|
||||
ma makro!(…) macro_rules! makro
|
||||
kw crate::
|
||||
kw self::
|
||||
"#]],
|
||||
);
|
||||
check(
|
||||
// Method
|
||||
r#"
|
||||
const X: usize = 0;
|
||||
struct Foo;
|
||||
|
@ -790,6 +741,11 @@ fn main() {
|
|||
Foo.bar::<_, $0>();
|
||||
}
|
||||
"#,
|
||||
];
|
||||
|
||||
for case in type_completion_cases {
|
||||
check(
|
||||
case,
|
||||
expect![[r#"
|
||||
en Enum
|
||||
ma makro!(…) macro_rules! makro
|
||||
|
@ -804,7 +760,8 @@ fn main() {
|
|||
kw crate::
|
||||
kw self::
|
||||
"#]],
|
||||
);
|
||||
)
|
||||
}
|
||||
|
||||
check(
|
||||
r#"
|
||||
|
@ -813,24 +770,7 @@ struct Foo;
|
|||
trait Bar {
|
||||
type Baz<T, const X: usize>;
|
||||
}
|
||||
fn foo<T: Bar<Baz<(), $0> = ()>>() {}
|
||||
"#,
|
||||
expect![[r#"
|
||||
ct CONST
|
||||
ct X
|
||||
ma makro!(…) macro_rules! makro
|
||||
kw crate::
|
||||
kw self::
|
||||
"#]],
|
||||
);
|
||||
check(
|
||||
r#"
|
||||
const X: usize = 0;
|
||||
struct Foo;
|
||||
trait Bar {
|
||||
type Baz<T, const X: usize>;
|
||||
}
|
||||
fn foo<T: Bar<Baz<F$0, 0> = ()>>() {}
|
||||
fn foo(_: impl Bar<Baz<F$0, 0> = ()>) {}
|
||||
"#,
|
||||
expect![[r#"
|
||||
en Enum
|
||||
|
@ -842,11 +782,91 @@ fn foo<T: Bar<Baz<F$0, 0> = ()>>() {}
|
|||
st Unit
|
||||
tt Bar
|
||||
tt Trait
|
||||
tp T
|
||||
un Union
|
||||
bt u32
|
||||
kw crate::
|
||||
kw self::
|
||||
"#]],
|
||||
);
|
||||
|
||||
let const_completion_cases = [
|
||||
// Function params
|
||||
r#"
|
||||
struct Foo;
|
||||
const X: usize = 0;
|
||||
fn foo<T, const N: usize>() {}
|
||||
fn main() {
|
||||
foo::<_, $0>();
|
||||
}
|
||||
"#,
|
||||
// Method params
|
||||
r#"
|
||||
const X: usize = 0;
|
||||
struct Foo;
|
||||
impl Foo { fn bar<const N: usize, T>(self) {} }
|
||||
fn main() {
|
||||
Foo.bar::<X$0, _>();
|
||||
}
|
||||
"#,
|
||||
// Associated type params
|
||||
r#"
|
||||
const X: usize = 0;
|
||||
struct Foo;
|
||||
trait Bar {
|
||||
type Baz<T, const X: usize>;
|
||||
}
|
||||
fn foo<T: Bar<Baz<(), $0> = ()>>() {}
|
||||
"#,
|
||||
// Type params
|
||||
r#"
|
||||
const X: usize = 0;
|
||||
struct Foo<T, const N: usize>(T);
|
||||
fn main() {
|
||||
let _: Foo::<_, $0> = todo!();
|
||||
}
|
||||
"#,
|
||||
// Enum variant params
|
||||
r#"
|
||||
const X: usize = 0;
|
||||
struct Foo<T, const N: usize>(T);
|
||||
type Bar<const X: usize, U> = Foo<U, X>;
|
||||
fn main() {
|
||||
let _: Bar::<X$0, _> = todo!();
|
||||
}
|
||||
"#,
|
||||
r#"
|
||||
const X: usize = 0;
|
||||
enum Foo<T, const N: usize> { A(T), B }
|
||||
fn main() {
|
||||
Foo::B::<(), $0>;
|
||||
}
|
||||
"#,
|
||||
// Trait params
|
||||
r#"
|
||||
const X: usize = 0;
|
||||
trait Foo<T, const N: usize> {}
|
||||
impl Foo<(), $0> for () {}
|
||||
"#,
|
||||
// Trait alias params
|
||||
r#"
|
||||
#![feature(trait_alias)]
|
||||
const X: usize = 0;
|
||||
trait Foo<T, const N: usize> {}
|
||||
trait Bar<const M: usize, U> = Foo<U, M>;
|
||||
fn foo<T: Bar<X$0, ()>>() {}
|
||||
"#,
|
||||
];
|
||||
|
||||
for case in const_completion_cases {
|
||||
check(
|
||||
case,
|
||||
expect![[r#"
|
||||
ct CONST
|
||||
ct X
|
||||
ma makro!(…) macro_rules! makro
|
||||
kw crate::
|
||||
kw self::
|
||||
"#]],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue