support AssocTypeArg and MethodCalls
This commit is contained in:
parent
b9ee4a5167
commit
f4038a6bf1
@ -719,6 +719,70 @@ fn classify_name_ref(
|
|||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let generic_arg_location = |arg: ast::GenericArg| {
|
||||||
|
let location = find_opt_node_in_file_compensated(
|
||||||
|
sema,
|
||||||
|
original_file,
|
||||||
|
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! {
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
_ => None,
|
||||||
|
},
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
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)
|
||||||
|
},
|
||||||
|
ast::AssocTypeArg(arg) => {
|
||||||
|
let trait_ = ast::PathSegment::cast(arg.syntax().parent()?.parent()?)?;
|
||||||
|
match sema.resolve_path(&trait_.parent_path().top_path())? {
|
||||||
|
hir::PathResolution::Def(def) => match def {
|
||||||
|
hir::ModuleDef::Trait(trait_) => {
|
||||||
|
let trait_items = trait_.items(sema.db);
|
||||||
|
let assoc_ty = trait_items.iter().find_map(|item| match item {
|
||||||
|
hir::AssocItem::TypeAlias(assoc_ty) => {
|
||||||
|
(assoc_ty.name(sema.db).as_str()? == arg.name_ref()?.text())
|
||||||
|
.then_some(assoc_ty)
|
||||||
|
},
|
||||||
|
_ => None,
|
||||||
|
})?;
|
||||||
|
let src = assoc_ty.source(sema.db)?;
|
||||||
|
let params = src.value.generic_param_list()?;
|
||||||
|
params.generic_params().nth(param_idx)
|
||||||
|
}
|
||||||
|
_ => None,
|
||||||
|
},
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
(args, param)
|
||||||
|
});
|
||||||
|
TypeLocation::GenericArgList(location)
|
||||||
|
};
|
||||||
|
|
||||||
let type_location = |node: &SyntaxNode| {
|
let type_location = |node: &SyntaxNode| {
|
||||||
let parent = node.parent()?;
|
let parent = node.parent()?;
|
||||||
let res = match_ast! {
|
let res = match_ast! {
|
||||||
@ -774,34 +838,8 @@ fn classify_name_ref(
|
|||||||
ast::TypeBound(_) => TypeLocation::TypeBound,
|
ast::TypeBound(_) => TypeLocation::TypeBound,
|
||||||
// is this case needed?
|
// is this case needed?
|
||||||
ast::TypeBoundList(_) => TypeLocation::TypeBound,
|
ast::TypeBoundList(_) => TypeLocation::TypeBound,
|
||||||
ast::GenericArg(it) => {
|
ast::TypeArg(it) => generic_arg_location(ast::GenericArg::TypeArg(it)),
|
||||||
let location = find_opt_node_in_file_compensated(sema, original_file, it.syntax().parent().and_then(ast::GenericArgList::cast))
|
ast::GenericArg(it) => generic_arg_location(it),
|
||||||
.map(|args| {
|
|
||||||
// Determine the index of the parameter in the `GenericArgList`
|
|
||||||
// (subtract 1 because `siblings` includes the node itself)
|
|
||||||
let param_idx = it.syntax().siblings(Direction::Prev).count() - 1;
|
|
||||||
let param = args
|
|
||||||
.syntax()
|
|
||||||
.parent()
|
|
||||||
.and_then(|p| ast::PathSegment::cast(p))
|
|
||||||
.and_then(|segment| sema.resolve_path(&segment.parent_path().top_path()))
|
|
||||||
.and_then(|resolved| {
|
|
||||||
match resolved {
|
|
||||||
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)
|
|
||||||
}
|
|
||||||
_ => None,
|
|
||||||
},
|
|
||||||
_ => None,
|
|
||||||
}
|
|
||||||
});
|
|
||||||
(args, param)
|
|
||||||
});
|
|
||||||
TypeLocation::GenericArgList(location)
|
|
||||||
},
|
|
||||||
// is this case needed?
|
// is this case needed?
|
||||||
ast::GenericArgList(it) => {
|
ast::GenericArgList(it) => {
|
||||||
let location = find_opt_node_in_file_compensated(sema, original_file, Some(it))
|
let location = find_opt_node_in_file_compensated(sema, original_file, Some(it))
|
||||||
|
@ -724,11 +724,70 @@ struct Foo {
|
|||||||
fn completes_const_and_type_generics_separately() {
|
fn completes_const_and_type_generics_separately() {
|
||||||
check(
|
check(
|
||||||
r#"
|
r#"
|
||||||
struct Foo;
|
struct Foo;
|
||||||
|
const X: usize = 0;
|
||||||
|
fn foo<T, const N: usize>() {}
|
||||||
|
fn main() {
|
||||||
|
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;
|
const X: usize = 0;
|
||||||
fn foo<T, const N: usize>() {}
|
struct Foo;
|
||||||
|
impl Foo { fn bar<const N: usize, T>(self) {} }
|
||||||
fn main() {
|
fn main() {
|
||||||
foo::<F$0, _>();
|
Foo.bar::<X$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::<_, $0>();
|
||||||
}
|
}
|
||||||
"#,
|
"#,
|
||||||
expect![[r#"
|
expect![[r#"
|
||||||
@ -746,14 +805,15 @@ fn main() {
|
|||||||
kw self::
|
kw self::
|
||||||
"#]],
|
"#]],
|
||||||
);
|
);
|
||||||
|
|
||||||
check(
|
check(
|
||||||
r#"
|
r#"
|
||||||
struct Foo;
|
|
||||||
const X: usize = 0;
|
const X: usize = 0;
|
||||||
fn foo<T, const N: usize>() {}
|
struct Foo;
|
||||||
fn main() {
|
trait Bar {
|
||||||
foo::<_, $0>();
|
type Baz<T, const X: usize>;
|
||||||
}
|
}
|
||||||
|
fn foo<T: Bar<Baz<(), $0> = ()>>() {}
|
||||||
"#,
|
"#,
|
||||||
expect![[r#"
|
expect![[r#"
|
||||||
ct CONST
|
ct CONST
|
||||||
@ -763,4 +823,30 @@ fn main() {
|
|||||||
kw self::
|
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#"
|
||||||
|
en Enum
|
||||||
|
ma makro!(…) macro_rules! makro
|
||||||
|
md module
|
||||||
|
st Foo
|
||||||
|
st Record
|
||||||
|
st Tuple
|
||||||
|
st Unit
|
||||||
|
tt Bar
|
||||||
|
tt Trait
|
||||||
|
tp T
|
||||||
|
un Union
|
||||||
|
bt u32
|
||||||
|
kw crate::
|
||||||
|
kw self::
|
||||||
|
"#]],
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user