mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-09-27 12:29:21 +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;
|
return;
|
||||||
}
|
}
|
||||||
TypeLocation::GenericArgList(Some((arg_list, generic_param))) => {
|
TypeLocation::GenericArgList(Some((arg_list, _))) => {
|
||||||
let in_assoc_type_arg = ctx
|
let in_assoc_type_arg = ctx
|
||||||
.original_token
|
.original_token
|
||||||
.parent_ancestors()
|
.parent_ancestors()
|
||||||
|
|
|
@ -726,20 +726,30 @@ fn classify_name_ref(
|
||||||
arg.syntax().parent().and_then(ast::GenericArgList::cast),
|
arg.syntax().parent().and_then(ast::GenericArgList::cast),
|
||||||
)
|
)
|
||||||
.map(|args| {
|
.map(|args| {
|
||||||
// Determine the index of the parameter in the `GenericArgList`
|
let param = (|| {
|
||||||
// (subtract 1 because `siblings` includes the node itself)
|
let parent = args.syntax().parent()?;
|
||||||
let param_idx = arg.syntax().siblings(Direction::Prev).count() - 1;
|
let params = match_ast! {
|
||||||
let parent = args.syntax().parent();
|
|
||||||
let param = parent.and_then(|parent| {
|
|
||||||
match_ast! {
|
|
||||||
match parent {
|
match parent {
|
||||||
ast::PathSegment(segment) => {
|
ast::PathSegment(segment) => {
|
||||||
match sema.resolve_path(&segment.parent_path().top_path())? {
|
match sema.resolve_path(&segment.parent_path().top_path())? {
|
||||||
hir::PathResolution::Def(def) => match def {
|
hir::PathResolution::Def(def) => match def {
|
||||||
hir::ModuleDef::Function(func) => {
|
hir::ModuleDef::Function(func) => {
|
||||||
let src = func.source(sema.db)?;
|
func.source(sema.db)?.value.generic_param_list()
|
||||||
let params = src.value.generic_param_list()?;
|
}
|
||||||
params.generic_params().nth(param_idx)
|
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,
|
_ => None,
|
||||||
},
|
},
|
||||||
|
@ -748,9 +758,7 @@ fn classify_name_ref(
|
||||||
},
|
},
|
||||||
ast::MethodCallExpr(call) => {
|
ast::MethodCallExpr(call) => {
|
||||||
let func = sema.resolve_method_call(&call)?;
|
let func = sema.resolve_method_call(&call)?;
|
||||||
let src = func.source(sema.db)?;
|
func.source(sema.db)?.value.generic_param_list()
|
||||||
let params = src.value.generic_param_list()?;
|
|
||||||
params.generic_params().nth(param_idx)
|
|
||||||
},
|
},
|
||||||
ast::AssocTypeArg(arg) => {
|
ast::AssocTypeArg(arg) => {
|
||||||
let trait_ = ast::PathSegment::cast(arg.syntax().parent()?.parent()?)?;
|
let trait_ = ast::PathSegment::cast(arg.syntax().parent()?.parent()?)?;
|
||||||
|
@ -765,19 +773,21 @@ fn classify_name_ref(
|
||||||
},
|
},
|
||||||
_ => None,
|
_ => None,
|
||||||
})?;
|
})?;
|
||||||
let src = assoc_ty.source(sema.db)?;
|
assoc_ty.source(sema.db)?.value.generic_param_list()
|
||||||
let params = src.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)
|
params.generic_params().nth(param_idx)
|
||||||
}
|
})();
|
||||||
_ => None,
|
|
||||||
},
|
|
||||||
_ => None,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
_ => None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
(args, param)
|
(args, param)
|
||||||
});
|
});
|
||||||
TypeLocation::GenericArgList(location)
|
TypeLocation::GenericArgList(location)
|
||||||
|
|
|
@ -722,7 +722,8 @@ pub struct S;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn completes_const_and_type_generics_separately() {
|
fn completes_const_and_type_generics_separately() {
|
||||||
check(
|
let type_completion_cases = [
|
||||||
|
// Function
|
||||||
r#"
|
r#"
|
||||||
struct Foo;
|
struct Foo;
|
||||||
const X: usize = 0;
|
const X: usize = 0;
|
||||||
|
@ -731,57 +732,7 @@ fn completes_const_and_type_generics_separately() {
|
||||||
foo::<F$0, _>();
|
foo::<F$0, _>();
|
||||||
}
|
}
|
||||||
"#,
|
"#,
|
||||||
expect![[r#"
|
// Method
|
||||||
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(
|
|
||||||
r#"
|
r#"
|
||||||
const X: usize = 0;
|
const X: usize = 0;
|
||||||
struct Foo;
|
struct Foo;
|
||||||
|
@ -790,6 +741,11 @@ fn main() {
|
||||||
Foo.bar::<_, $0>();
|
Foo.bar::<_, $0>();
|
||||||
}
|
}
|
||||||
"#,
|
"#,
|
||||||
|
];
|
||||||
|
|
||||||
|
for case in type_completion_cases {
|
||||||
|
check(
|
||||||
|
case,
|
||||||
expect![[r#"
|
expect![[r#"
|
||||||
en Enum
|
en Enum
|
||||||
ma makro!(…) macro_rules! makro
|
ma makro!(…) macro_rules! makro
|
||||||
|
@ -804,7 +760,8 @@ fn main() {
|
||||||
kw crate::
|
kw crate::
|
||||||
kw self::
|
kw self::
|
||||||
"#]],
|
"#]],
|
||||||
);
|
)
|
||||||
|
}
|
||||||
|
|
||||||
check(
|
check(
|
||||||
r#"
|
r#"
|
||||||
|
@ -813,24 +770,7 @@ struct Foo;
|
||||||
trait Bar {
|
trait Bar {
|
||||||
type Baz<T, const X: usize>;
|
type Baz<T, const X: usize>;
|
||||||
}
|
}
|
||||||
fn foo<T: Bar<Baz<(), $0> = ()>>() {}
|
fn foo(_: impl Bar<Baz<F$0, 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> = ()>>() {}
|
|
||||||
"#,
|
"#,
|
||||||
expect![[r#"
|
expect![[r#"
|
||||||
en Enum
|
en Enum
|
||||||
|
@ -842,11 +782,91 @@ fn foo<T: Bar<Baz<F$0, 0> = ()>>() {}
|
||||||
st Unit
|
st Unit
|
||||||
tt Bar
|
tt Bar
|
||||||
tt Trait
|
tt Trait
|
||||||
tp T
|
|
||||||
un Union
|
un Union
|
||||||
bt u32
|
bt u32
|
||||||
kw crate::
|
kw crate::
|
||||||
kw self::
|
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