2020-07-04 10:03:27 +02:00
|
|
|
//! Completes references after dot (fields and method calls).
|
2019-09-30 11:58:53 +03:00
|
|
|
|
2022-04-25 18:51:59 +02:00
|
|
|
use ide_db::FxHashSet;
|
2019-01-08 22:33:36 +03:00
|
|
|
|
2022-05-06 12:04:41 +02:00
|
|
|
use crate::{
|
2022-06-20 14:23:46 +02:00
|
|
|
context::{CompletionContext, DotAccess, DotAccessKind, ExprCtx, PathCompletionCtx, Qualified},
|
2022-05-23 17:40:41 +02:00
|
|
|
CompletionItem, CompletionItemKind, Completions,
|
2022-05-06 12:04:41 +02:00
|
|
|
};
|
2019-01-08 22:33:36 +03:00
|
|
|
|
2020-07-04 10:36:12 +02:00
|
|
|
/// Complete dot accesses, i.e. fields or methods.
|
2022-07-20 15:06:15 +02:00
|
|
|
pub(crate) fn complete_dot(
|
|
|
|
acc: &mut Completions,
|
|
|
|
ctx: &CompletionContext<'_>,
|
|
|
|
dot_access: &DotAccess,
|
|
|
|
) {
|
2022-06-17 23:36:39 +02:00
|
|
|
let receiver_ty = match dot_access {
|
|
|
|
DotAccess { receiver_ty: Some(receiver_ty), .. } => &receiver_ty.original,
|
|
|
|
_ => return,
|
2019-08-04 08:03:17 +07:00
|
|
|
};
|
2019-08-03 01:15:43 +07:00
|
|
|
|
2022-05-23 17:40:41 +02:00
|
|
|
// Suggest .await syntax for types that implement Future trait
|
2022-08-16 17:53:10 -04:00
|
|
|
if receiver_ty.impls_into_future(ctx.db) {
|
2022-05-23 17:40:41 +02:00
|
|
|
let mut item =
|
|
|
|
CompletionItem::new(CompletionItemKind::Keyword, ctx.source_range(), "await");
|
|
|
|
item.detail("expr.await");
|
2023-05-24 18:04:29 +02:00
|
|
|
item.add_to(acc, ctx.db);
|
2022-05-23 17:40:41 +02:00
|
|
|
}
|
2019-08-03 01:15:43 +07:00
|
|
|
|
2023-11-22 18:33:38 +05:30
|
|
|
let is_field_access = matches!(dot_access.kind, DotAccessKind::Field { .. });
|
2023-12-08 16:16:01 +05:30
|
|
|
let is_method_acces_with_parens =
|
|
|
|
matches!(dot_access.kind, DotAccessKind::Method { has_parens: true });
|
2023-11-22 18:33:38 +05:30
|
|
|
|
|
|
|
complete_fields(
|
|
|
|
acc,
|
|
|
|
ctx,
|
|
|
|
receiver_ty,
|
|
|
|
|acc, field, ty| acc.add_field(ctx, dot_access, None, field, &ty),
|
|
|
|
|acc, field, ty| acc.add_tuple_field(ctx, None, field, &ty),
|
|
|
|
is_field_access,
|
2023-12-08 16:16:01 +05:30
|
|
|
is_method_acces_with_parens,
|
2023-11-22 18:33:38 +05:30
|
|
|
);
|
|
|
|
|
2022-12-30 08:05:03 +00:00
|
|
|
complete_methods(ctx, receiver_ty, |func| acc.add_method(ctx, dot_access, func, None, None));
|
2021-05-28 15:09:10 +02:00
|
|
|
}
|
|
|
|
|
2022-06-17 23:36:39 +02:00
|
|
|
pub(crate) fn complete_undotted_self(
|
|
|
|
acc: &mut Completions,
|
2022-07-20 15:02:08 +02:00
|
|
|
ctx: &CompletionContext<'_>,
|
2022-06-17 23:36:39 +02:00
|
|
|
path_ctx: &PathCompletionCtx,
|
2022-06-20 14:23:46 +02:00
|
|
|
expr_ctx: &ExprCtx,
|
2022-06-17 23:36:39 +02:00
|
|
|
) {
|
2021-06-02 15:21:18 +02:00
|
|
|
if !ctx.config.enable_self_on_the_fly {
|
|
|
|
return;
|
|
|
|
}
|
2022-06-20 14:23:46 +02:00
|
|
|
if !path_ctx.is_trivial_path() {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if !ctx.qualifier_ctx.none() {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if !matches!(path_ctx.qualified, Qualified::No) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
let self_param = match expr_ctx {
|
|
|
|
ExprCtx { self_param: Some(self_param), .. } => self_param,
|
2022-05-06 12:04:41 +02:00
|
|
|
_ => return,
|
2022-06-18 09:54:03 +02:00
|
|
|
};
|
2022-05-06 12:04:41 +02:00
|
|
|
|
2022-06-18 09:54:03 +02:00
|
|
|
let ty = self_param.ty(ctx.db);
|
|
|
|
complete_fields(
|
|
|
|
acc,
|
|
|
|
ctx,
|
|
|
|
&ty,
|
2022-06-20 20:22:51 +02:00
|
|
|
|acc, field, ty| {
|
|
|
|
acc.add_field(
|
|
|
|
ctx,
|
|
|
|
&DotAccess {
|
|
|
|
receiver: None,
|
|
|
|
receiver_ty: None,
|
|
|
|
kind: DotAccessKind::Field { receiver_is_ambiguous_float_literal: false },
|
|
|
|
},
|
|
|
|
Some(hir::known::SELF_PARAM),
|
|
|
|
field,
|
|
|
|
&ty,
|
|
|
|
)
|
|
|
|
},
|
2022-06-18 09:54:03 +02:00
|
|
|
|acc, field, ty| acc.add_tuple_field(ctx, Some(hir::known::SELF_PARAM), field, &ty),
|
2023-11-22 18:33:38 +05:30
|
|
|
true,
|
2023-12-08 16:16:01 +05:30
|
|
|
false,
|
2022-06-18 09:54:03 +02:00
|
|
|
);
|
|
|
|
complete_methods(ctx, &ty, |func| {
|
2022-06-20 17:41:04 +02:00
|
|
|
acc.add_method(
|
|
|
|
ctx,
|
|
|
|
&DotAccess {
|
|
|
|
receiver: None,
|
|
|
|
receiver_ty: None,
|
|
|
|
kind: DotAccessKind::Method { has_parens: false },
|
|
|
|
},
|
|
|
|
func,
|
|
|
|
Some(hir::known::SELF_PARAM),
|
|
|
|
None,
|
|
|
|
)
|
2022-06-18 09:54:03 +02:00
|
|
|
});
|
2021-05-28 15:09:10 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
fn complete_fields(
|
2022-04-25 18:40:38 +02:00
|
|
|
acc: &mut Completions,
|
2022-07-20 15:02:08 +02:00
|
|
|
ctx: &CompletionContext<'_>,
|
2021-05-28 15:09:10 +02:00
|
|
|
receiver: &hir::Type,
|
2022-04-25 18:40:38 +02:00
|
|
|
mut named_field: impl FnMut(&mut Completions, hir::Field, hir::Type),
|
|
|
|
mut tuple_index: impl FnMut(&mut Completions, usize, hir::Type),
|
2023-11-22 18:33:38 +05:30
|
|
|
is_field_access: bool,
|
2023-12-08 16:16:01 +05:30
|
|
|
is_method_acess_with_parens: bool,
|
2021-05-28 15:09:10 +02:00
|
|
|
) {
|
2023-06-11 19:16:13 +09:00
|
|
|
let mut seen_names = FxHashSet::default();
|
2021-05-28 15:09:10 +02:00
|
|
|
for receiver in receiver.autoderef(ctx.db) {
|
|
|
|
for (field, ty) in receiver.fields(ctx.db) {
|
2023-11-22 18:33:38 +05:30
|
|
|
if seen_names.insert(field.name(ctx.db))
|
2023-12-08 16:16:01 +05:30
|
|
|
&& (is_field_access
|
|
|
|
|| (is_method_acess_with_parens && (ty.is_fn() || ty.is_closure())))
|
2023-11-22 18:33:38 +05:30
|
|
|
{
|
2023-06-11 19:16:13 +09:00
|
|
|
named_field(acc, field, ty);
|
|
|
|
}
|
2021-05-28 15:09:10 +02:00
|
|
|
}
|
|
|
|
for (i, ty) in receiver.tuple_fields(ctx.db).into_iter().enumerate() {
|
2023-06-13 17:32:00 +09:00
|
|
|
// Tuples are always the last type in a deref chain, so just check if the name is
|
|
|
|
// already seen without inserting into the hashset.
|
2023-11-22 18:33:38 +05:30
|
|
|
if !seen_names.contains(&hir::Name::new_tuple_field(i))
|
2023-12-08 16:16:01 +05:30
|
|
|
&& (is_field_access
|
|
|
|
|| (is_method_acess_with_parens && (ty.is_fn() || ty.is_closure())))
|
2023-11-22 18:33:38 +05:30
|
|
|
{
|
2023-06-13 17:32:00 +09:00
|
|
|
// Tuple fields are always public (tuple struct fields are handled above).
|
|
|
|
tuple_index(acc, i, ty);
|
|
|
|
}
|
2021-05-28 15:09:10 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn complete_methods(
|
2022-07-20 15:02:08 +02:00
|
|
|
ctx: &CompletionContext<'_>,
|
2021-05-28 15:09:10 +02:00
|
|
|
receiver: &hir::Type,
|
|
|
|
mut f: impl FnMut(hir::Function),
|
|
|
|
) {
|
Refactor autoderef and method resolution
- don't return the receiver type from method resolution; instead just
return the autorefs/autoderefs that happened and repeat them. This
ensures all the effects like trait obligations and whatever we learned
about type variables from derefing them are actually applied. Also, it
allows us to get rid of `decanonicalize_ty`, which was just wrong in
principle.
- Autoderef itself now directly works with an inference table. Sadly
this has the effect of making it harder to use as an iterator, often
requiring manual `while let` loops. (rustc works around this by using
inner mutability in the inference context, so that things like unifying
types don't require a unique reference.)
- We now record the adjustments (autoref/deref) for method receivers
and index expressions, which we didn't before.
- Removed the redundant crate parameter from method resolution, since
the trait_env contains the crate as well.
- in the HIR API, the methods now take a scope to determine the trait env.
`Type` carries a trait env, but I think that's probably a bad decision
because it's easy to create it with the wrong env, e.g. by using
`Adt::ty`. This mostly didn't matter so far because
`iterate_method_candidates` took a crate parameter and ignored
`self.krate`, but the trait env would still have been wrong in those
cases, which I think would give some wrong results in some edge cases.
Fixes #10058.
2022-02-16 17:44:03 +01:00
|
|
|
let mut seen_methods = FxHashSet::default();
|
2023-02-27 15:51:45 +01:00
|
|
|
receiver.iterate_method_candidates_with_traits(
|
Refactor autoderef and method resolution
- don't return the receiver type from method resolution; instead just
return the autorefs/autoderefs that happened and repeat them. This
ensures all the effects like trait obligations and whatever we learned
about type variables from derefing them are actually applied. Also, it
allows us to get rid of `decanonicalize_ty`, which was just wrong in
principle.
- Autoderef itself now directly works with an inference table. Sadly
this has the effect of making it harder to use as an iterator, often
requiring manual `while let` loops. (rustc works around this by using
inner mutability in the inference context, so that things like unifying
types don't require a unique reference.)
- We now record the adjustments (autoref/deref) for method receivers
and index expressions, which we didn't before.
- Removed the redundant crate parameter from method resolution, since
the trait_env contains the crate as well.
- in the HIR API, the methods now take a scope to determine the trait env.
`Type` carries a trait env, but I think that's probably a bad decision
because it's easy to create it with the wrong env, e.g. by using
`Adt::ty`. This mostly didn't matter so far because
`iterate_method_candidates` took a crate parameter and ignored
`self.krate`, but the trait env would still have been wrong in those
cases, which I think would give some wrong results in some edge cases.
Fixes #10058.
2022-02-16 17:44:03 +01:00
|
|
|
ctx.db,
|
|
|
|
&ctx.scope,
|
2022-06-20 21:55:33 +02:00
|
|
|
&ctx.traits_in_scope(),
|
2022-03-31 11:12:08 +02:00
|
|
|
Some(ctx.module),
|
Refactor autoderef and method resolution
- don't return the receiver type from method resolution; instead just
return the autorefs/autoderefs that happened and repeat them. This
ensures all the effects like trait obligations and whatever we learned
about type variables from derefing them are actually applied. Also, it
allows us to get rid of `decanonicalize_ty`, which was just wrong in
principle.
- Autoderef itself now directly works with an inference table. Sadly
this has the effect of making it harder to use as an iterator, often
requiring manual `while let` loops. (rustc works around this by using
inner mutability in the inference context, so that things like unifying
types don't require a unique reference.)
- We now record the adjustments (autoref/deref) for method receivers
and index expressions, which we didn't before.
- Removed the redundant crate parameter from method resolution, since
the trait_env contains the crate as well.
- in the HIR API, the methods now take a scope to determine the trait env.
`Type` carries a trait env, but I think that's probably a bad decision
because it's easy to create it with the wrong env, e.g. by using
`Adt::ty`. This mostly didn't matter so far because
`iterate_method_candidates` took a crate parameter and ignored
`self.krate`, but the trait env would still have been wrong in those
cases, which I think would give some wrong results in some edge cases.
Fixes #10058.
2022-02-16 17:44:03 +01:00
|
|
|
None,
|
|
|
|
|func| {
|
|
|
|
if func.self_param(ctx.db).is_some() && seen_methods.insert(func.name(ctx.db)) {
|
|
|
|
f(func);
|
|
|
|
}
|
|
|
|
None::<()>
|
|
|
|
},
|
|
|
|
);
|
2019-01-07 19:12:19 +01:00
|
|
|
}
|
|
|
|
|
2019-01-08 22:33:36 +03:00
|
|
|
#[cfg(test)]
|
|
|
|
mod tests {
|
2020-08-21 13:19:31 +02:00
|
|
|
use expect_test::{expect, Expect};
|
2020-07-04 10:36:12 +02:00
|
|
|
|
2022-06-16 08:52:57 +08:00
|
|
|
use crate::tests::{
|
|
|
|
check_edit, completion_list_no_kw, completion_list_no_kw_with_private_editable,
|
|
|
|
};
|
2019-01-08 22:33:36 +03:00
|
|
|
|
2020-07-04 10:36:12 +02:00
|
|
|
fn check(ra_fixture: &str, expect: Expect) {
|
2021-10-27 16:24:42 +02:00
|
|
|
let actual = completion_list_no_kw(ra_fixture);
|
2020-07-04 10:36:12 +02:00
|
|
|
expect.assert_eq(&actual);
|
2019-01-08 22:33:36 +03:00
|
|
|
}
|
|
|
|
|
2022-06-16 08:52:57 +08:00
|
|
|
fn check_with_private_editable(ra_fixture: &str, expect: Expect) {
|
|
|
|
let actual = completion_list_no_kw_with_private_editable(ra_fixture);
|
|
|
|
expect.assert_eq(&actual);
|
|
|
|
}
|
|
|
|
|
2019-01-08 22:33:36 +03:00
|
|
|
#[test]
|
2020-07-04 10:36:12 +02:00
|
|
|
fn test_struct_field_and_method_completion() {
|
|
|
|
check(
|
|
|
|
r#"
|
|
|
|
struct S { foo: u32 }
|
|
|
|
impl S {
|
|
|
|
fn bar(&self) {}
|
|
|
|
}
|
2021-01-06 20:15:48 +00:00
|
|
|
fn foo(s: S) { s.$0 }
|
2020-07-04 10:36:12 +02:00
|
|
|
"#,
|
|
|
|
expect![[r#"
|
2020-07-04 19:03:58 +02:00
|
|
|
fd foo u32
|
2021-03-06 16:56:07 -08:00
|
|
|
me bar() fn(&self)
|
2020-07-04 10:36:12 +02:00
|
|
|
"#]],
|
2019-01-08 22:33:36 +03:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2023-04-11 21:10:25 +09:00
|
|
|
#[test]
|
|
|
|
fn no_unstable_method_on_stable() {
|
|
|
|
check(
|
|
|
|
r#"
|
|
|
|
//- /main.rs crate:main deps:std
|
|
|
|
fn foo(s: std::S) { s.$0 }
|
|
|
|
//- /std.rs crate:std
|
|
|
|
pub struct S;
|
|
|
|
impl S {
|
|
|
|
#[unstable]
|
|
|
|
pub fn bar(&self) {}
|
|
|
|
}
|
|
|
|
"#,
|
|
|
|
expect![""],
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn unstable_method_on_nightly() {
|
|
|
|
check(
|
|
|
|
r#"
|
|
|
|
//- toolchain:nightly
|
|
|
|
//- /main.rs crate:main deps:std
|
|
|
|
fn foo(s: std::S) { s.$0 }
|
|
|
|
//- /std.rs crate:std
|
|
|
|
pub struct S;
|
|
|
|
impl S {
|
|
|
|
#[unstable]
|
|
|
|
pub fn bar(&self) {}
|
|
|
|
}
|
|
|
|
"#,
|
|
|
|
expect![[r#"
|
|
|
|
me bar() fn(&self)
|
|
|
|
"#]],
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2019-01-08 22:33:36 +03:00
|
|
|
#[test]
|
|
|
|
fn test_struct_field_completion_self() {
|
2020-07-04 10:36:12 +02:00
|
|
|
check(
|
|
|
|
r#"
|
|
|
|
struct S { the_field: (u32,) }
|
|
|
|
impl S {
|
2021-01-06 20:15:48 +00:00
|
|
|
fn foo(self) { self.$0 }
|
2020-07-04 10:36:12 +02:00
|
|
|
}
|
|
|
|
"#,
|
|
|
|
expect![[r#"
|
|
|
|
fd the_field (u32,)
|
2021-03-06 16:56:07 -08:00
|
|
|
me foo() fn(self)
|
2020-07-04 10:36:12 +02:00
|
|
|
"#]],
|
|
|
|
)
|
2019-01-08 22:33:36 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_struct_field_completion_autoderef() {
|
2020-07-04 10:36:12 +02:00
|
|
|
check(
|
|
|
|
r#"
|
|
|
|
struct A { the_field: (u32, i32) }
|
|
|
|
impl A {
|
2021-01-06 20:15:48 +00:00
|
|
|
fn foo(&self) { self.$0 }
|
2020-07-04 10:36:12 +02:00
|
|
|
}
|
|
|
|
"#,
|
|
|
|
expect![[r#"
|
|
|
|
fd the_field (u32, i32)
|
2021-03-06 16:56:07 -08:00
|
|
|
me foo() fn(&self)
|
2020-07-04 10:36:12 +02:00
|
|
|
"#]],
|
|
|
|
)
|
2019-01-08 22:33:36 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_no_struct_field_completion_for_method_call() {
|
2020-07-04 10:36:12 +02:00
|
|
|
check(
|
|
|
|
r#"
|
|
|
|
struct A { the_field: u32 }
|
2021-01-06 20:15:48 +00:00
|
|
|
fn foo(a: A) { a.$0() }
|
2020-07-04 10:36:12 +02:00
|
|
|
"#,
|
2021-10-27 17:18:42 +02:00
|
|
|
expect![[r#""#]],
|
2019-01-08 22:33:36 +03:00
|
|
|
);
|
|
|
|
}
|
2019-01-07 19:12:19 +01:00
|
|
|
|
2019-12-24 21:46:07 +01:00
|
|
|
#[test]
|
2020-07-04 10:36:12 +02:00
|
|
|
fn test_visibility_filtering() {
|
|
|
|
check(
|
|
|
|
r#"
|
2021-07-23 19:57:16 +02:00
|
|
|
//- /lib.rs crate:lib new_source_root:local
|
|
|
|
pub mod m {
|
2020-07-04 10:36:12 +02:00
|
|
|
pub struct A {
|
|
|
|
private_field: u32,
|
|
|
|
pub pub_field: u32,
|
|
|
|
pub(crate) crate_field: u32,
|
2021-07-23 19:57:16 +02:00
|
|
|
pub(super) super_field: u32,
|
2020-04-28 22:45:46 +02:00
|
|
|
}
|
2020-07-04 10:36:12 +02:00
|
|
|
}
|
2021-07-23 19:57:16 +02:00
|
|
|
//- /main.rs crate:main deps:lib new_source_root:local
|
|
|
|
fn foo(a: lib::m::A) { a.$0 }
|
2022-06-16 08:52:57 +08:00
|
|
|
"#,
|
|
|
|
expect![[r#"
|
|
|
|
fd pub_field u32
|
|
|
|
"#]],
|
|
|
|
);
|
|
|
|
|
|
|
|
check(
|
|
|
|
r#"
|
|
|
|
//- /lib.rs crate:lib new_source_root:library
|
|
|
|
pub mod m {
|
|
|
|
pub struct A {
|
|
|
|
private_field: u32,
|
|
|
|
pub pub_field: u32,
|
|
|
|
pub(crate) crate_field: u32,
|
|
|
|
pub(super) super_field: u32,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
//- /main.rs crate:main deps:lib new_source_root:local
|
|
|
|
fn foo(a: lib::m::A) { a.$0 }
|
|
|
|
"#,
|
|
|
|
expect![[r#"
|
|
|
|
fd pub_field u32
|
|
|
|
"#]],
|
|
|
|
);
|
|
|
|
|
|
|
|
check(
|
|
|
|
r#"
|
|
|
|
//- /lib.rs crate:lib new_source_root:library
|
|
|
|
pub mod m {
|
|
|
|
pub struct A(
|
|
|
|
i32,
|
|
|
|
pub f64,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
//- /main.rs crate:main deps:lib new_source_root:local
|
|
|
|
fn foo(a: lib::m::A) { a.$0 }
|
|
|
|
"#,
|
|
|
|
expect![[r#"
|
|
|
|
fd 1 f64
|
|
|
|
"#]],
|
|
|
|
);
|
|
|
|
|
|
|
|
check(
|
|
|
|
r#"
|
|
|
|
//- /lib.rs crate:lib new_source_root:local
|
|
|
|
pub struct A {}
|
|
|
|
mod m {
|
|
|
|
impl super::A {
|
|
|
|
fn private_method(&self) {}
|
|
|
|
pub(crate) fn crate_method(&self) {}
|
|
|
|
pub fn pub_method(&self) {}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
//- /main.rs crate:main deps:lib new_source_root:local
|
|
|
|
fn foo(a: lib::A) { a.$0 }
|
|
|
|
"#,
|
|
|
|
expect![[r#"
|
|
|
|
me pub_method() fn(&self)
|
|
|
|
"#]],
|
|
|
|
);
|
|
|
|
check(
|
|
|
|
r#"
|
|
|
|
//- /lib.rs crate:lib new_source_root:library
|
|
|
|
pub struct A {}
|
|
|
|
mod m {
|
|
|
|
impl super::A {
|
|
|
|
fn private_method(&self) {}
|
|
|
|
pub(crate) fn crate_method(&self) {}
|
|
|
|
pub fn pub_method(&self) {}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
//- /main.rs crate:main deps:lib new_source_root:local
|
|
|
|
fn foo(a: lib::A) { a.$0 }
|
|
|
|
"#,
|
|
|
|
expect![[r#"
|
|
|
|
me pub_method() fn(&self)
|
|
|
|
"#]],
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_visibility_filtering_with_private_editable_enabled() {
|
|
|
|
check_with_private_editable(
|
|
|
|
r#"
|
|
|
|
//- /lib.rs crate:lib new_source_root:local
|
|
|
|
pub mod m {
|
|
|
|
pub struct A {
|
|
|
|
private_field: u32,
|
|
|
|
pub pub_field: u32,
|
|
|
|
pub(crate) crate_field: u32,
|
|
|
|
pub(super) super_field: u32,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
//- /main.rs crate:main deps:lib new_source_root:local
|
|
|
|
fn foo(a: lib::m::A) { a.$0 }
|
2020-07-04 10:36:12 +02:00
|
|
|
"#,
|
|
|
|
expect![[r#"
|
2022-05-05 10:49:43 +02:00
|
|
|
fd crate_field u32
|
2021-07-23 19:57:16 +02:00
|
|
|
fd private_field u32
|
|
|
|
fd pub_field u32
|
|
|
|
fd super_field u32
|
2020-07-04 10:36:12 +02:00
|
|
|
"#]],
|
2019-12-24 21:46:07 +01:00
|
|
|
);
|
|
|
|
|
2022-06-16 08:52:57 +08:00
|
|
|
check_with_private_editable(
|
2020-07-04 10:36:12 +02:00
|
|
|
r#"
|
2021-07-23 19:57:16 +02:00
|
|
|
//- /lib.rs crate:lib new_source_root:library
|
|
|
|
pub mod m {
|
|
|
|
pub struct A {
|
|
|
|
private_field: u32,
|
|
|
|
pub pub_field: u32,
|
|
|
|
pub(crate) crate_field: u32,
|
|
|
|
pub(super) super_field: u32,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
//- /main.rs crate:main deps:lib new_source_root:local
|
|
|
|
fn foo(a: lib::m::A) { a.$0 }
|
|
|
|
"#,
|
|
|
|
expect![[r#"
|
|
|
|
fd pub_field u32
|
|
|
|
"#]],
|
|
|
|
);
|
|
|
|
|
2022-06-16 08:52:57 +08:00
|
|
|
check_with_private_editable(
|
2021-07-23 20:20:23 +02:00
|
|
|
r#"
|
|
|
|
//- /lib.rs crate:lib new_source_root:library
|
|
|
|
pub mod m {
|
|
|
|
pub struct A(
|
|
|
|
i32,
|
|
|
|
pub f64,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
//- /main.rs crate:main deps:lib new_source_root:local
|
|
|
|
fn foo(a: lib::m::A) { a.$0 }
|
|
|
|
"#,
|
|
|
|
expect![[r#"
|
2021-10-27 17:18:42 +02:00
|
|
|
fd 1 f64
|
2021-07-23 20:20:23 +02:00
|
|
|
"#]],
|
|
|
|
);
|
|
|
|
|
2022-06-16 08:52:57 +08:00
|
|
|
check_with_private_editable(
|
2021-07-23 19:57:16 +02:00
|
|
|
r#"
|
|
|
|
//- /lib.rs crate:lib new_source_root:local
|
|
|
|
pub struct A {}
|
2020-07-04 10:36:12 +02:00
|
|
|
mod m {
|
|
|
|
impl super::A {
|
|
|
|
fn private_method(&self) {}
|
2021-07-23 19:57:16 +02:00
|
|
|
pub(crate) fn crate_method(&self) {}
|
|
|
|
pub fn pub_method(&self) {}
|
2020-07-04 10:36:12 +02:00
|
|
|
}
|
|
|
|
}
|
2021-07-23 19:57:16 +02:00
|
|
|
//- /main.rs crate:main deps:lib new_source_root:local
|
|
|
|
fn foo(a: lib::A) { a.$0 }
|
2020-07-04 10:36:12 +02:00
|
|
|
"#,
|
|
|
|
expect![[r#"
|
2021-07-23 19:57:16 +02:00
|
|
|
me crate_method() fn(&self)
|
2022-05-05 10:49:43 +02:00
|
|
|
me private_method() fn(&self)
|
2021-07-23 19:57:16 +02:00
|
|
|
me pub_method() fn(&self)
|
|
|
|
"#]],
|
|
|
|
);
|
2022-06-16 08:52:57 +08:00
|
|
|
check_with_private_editable(
|
2021-07-23 19:57:16 +02:00
|
|
|
r#"
|
|
|
|
//- /lib.rs crate:lib new_source_root:library
|
|
|
|
pub struct A {}
|
|
|
|
mod m {
|
|
|
|
impl super::A {
|
|
|
|
fn private_method(&self) {}
|
|
|
|
pub(crate) fn crate_method(&self) {}
|
|
|
|
pub fn pub_method(&self) {}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
//- /main.rs crate:main deps:lib new_source_root:local
|
|
|
|
fn foo(a: lib::A) { a.$0 }
|
|
|
|
"#,
|
|
|
|
expect![[r#"
|
|
|
|
me pub_method() fn(&self)
|
2020-07-04 10:36:12 +02:00
|
|
|
"#]],
|
2019-01-07 19:12:19 +01:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2022-02-01 23:29:40 +01:00
|
|
|
#[test]
|
|
|
|
fn test_local_impls() {
|
|
|
|
check(
|
|
|
|
r#"
|
|
|
|
pub struct A {}
|
|
|
|
mod m {
|
|
|
|
impl super::A {
|
|
|
|
pub fn pub_module_method(&self) {}
|
|
|
|
}
|
|
|
|
fn f() {
|
|
|
|
impl super::A {
|
|
|
|
pub fn pub_foreign_local_method(&self) {}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2023-03-14 19:36:28 +01:00
|
|
|
fn foo(a: A) {
|
|
|
|
impl A {
|
2022-02-01 23:29:40 +01:00
|
|
|
fn local_method(&self) {}
|
|
|
|
}
|
|
|
|
a.$0
|
|
|
|
}
|
|
|
|
"#,
|
|
|
|
expect![[r#"
|
|
|
|
me local_method() fn(&self)
|
|
|
|
me pub_module_method() fn(&self)
|
|
|
|
"#]],
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2021-07-23 15:36:43 +02:00
|
|
|
#[test]
|
|
|
|
fn test_doc_hidden_filtering() {
|
|
|
|
check(
|
|
|
|
r#"
|
|
|
|
//- /lib.rs crate:lib deps:dep
|
|
|
|
fn foo(a: dep::A) { a.$0 }
|
|
|
|
//- /dep.rs crate:dep
|
|
|
|
pub struct A {
|
|
|
|
#[doc(hidden)]
|
|
|
|
pub hidden_field: u32,
|
|
|
|
pub pub_field: u32,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl A {
|
|
|
|
pub fn pub_method(&self) {}
|
|
|
|
|
|
|
|
#[doc(hidden)]
|
|
|
|
pub fn hidden_method(&self) {}
|
|
|
|
}
|
|
|
|
"#,
|
|
|
|
expect![[r#"
|
|
|
|
fd pub_field u32
|
|
|
|
me pub_method() fn(&self)
|
2021-07-23 16:45:14 +02:00
|
|
|
"#]],
|
2021-07-23 15:36:43 +02:00
|
|
|
)
|
|
|
|
}
|
|
|
|
|
2019-12-02 19:27:31 +01:00
|
|
|
#[test]
|
2020-07-04 10:36:12 +02:00
|
|
|
fn test_union_field_completion() {
|
|
|
|
check(
|
|
|
|
r#"
|
|
|
|
union U { field: u8, other: u16 }
|
2021-01-06 20:15:48 +00:00
|
|
|
fn foo(u: U) { u.$0 }
|
2020-07-04 10:36:12 +02:00
|
|
|
"#,
|
|
|
|
expect![[r#"
|
|
|
|
fd field u8
|
|
|
|
fd other u16
|
|
|
|
"#]],
|
2019-12-02 19:27:31 +01:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2020-03-07 23:03:56 +01:00
|
|
|
#[test]
|
2020-07-04 10:36:12 +02:00
|
|
|
fn test_method_completion_only_fitting_impls() {
|
|
|
|
check(
|
|
|
|
r#"
|
|
|
|
struct A<T> {}
|
|
|
|
impl A<u32> {
|
|
|
|
fn the_method(&self) {}
|
|
|
|
}
|
|
|
|
impl A<i32> {
|
|
|
|
fn the_other_method(&self) {}
|
|
|
|
}
|
2021-01-06 20:15:48 +00:00
|
|
|
fn foo(a: A<u32>) { a.$0 }
|
2020-07-04 10:36:12 +02:00
|
|
|
"#,
|
|
|
|
expect![[r#"
|
2021-03-06 16:56:07 -08:00
|
|
|
me the_method() fn(&self)
|
2020-07-04 10:36:12 +02:00
|
|
|
"#]],
|
|
|
|
)
|
2020-03-07 23:03:56 +01:00
|
|
|
}
|
|
|
|
|
2019-04-14 16:08:10 +02:00
|
|
|
#[test]
|
|
|
|
fn test_trait_method_completion() {
|
2020-07-04 10:36:12 +02:00
|
|
|
check(
|
|
|
|
r#"
|
|
|
|
struct A {}
|
|
|
|
trait Trait { fn the_method(&self); }
|
|
|
|
impl Trait for A {}
|
2021-01-06 20:15:48 +00:00
|
|
|
fn foo(a: A) { a.$0 }
|
2020-07-04 10:36:12 +02:00
|
|
|
"#,
|
|
|
|
expect![[r#"
|
2021-07-05 16:44:44 +04:30
|
|
|
me the_method() (as Trait) fn(&self)
|
2020-07-04 10:36:12 +02:00
|
|
|
"#]],
|
2019-04-14 16:08:10 +02:00
|
|
|
);
|
2021-07-07 19:54:58 +02:00
|
|
|
check_edit(
|
|
|
|
"the_method",
|
|
|
|
r#"
|
|
|
|
struct A {}
|
|
|
|
trait Trait { fn the_method(&self); }
|
|
|
|
impl Trait for A {}
|
|
|
|
fn foo(a: A) { a.$0 }
|
|
|
|
"#,
|
|
|
|
r#"
|
|
|
|
struct A {}
|
|
|
|
trait Trait { fn the_method(&self); }
|
|
|
|
impl Trait for A {}
|
|
|
|
fn foo(a: A) { a.the_method()$0 }
|
|
|
|
"#,
|
|
|
|
);
|
2019-04-14 16:08:10 +02:00
|
|
|
}
|
|
|
|
|
2019-06-29 12:19:03 +02:00
|
|
|
#[test]
|
|
|
|
fn test_trait_method_completion_deduplicated() {
|
2020-07-04 10:36:12 +02:00
|
|
|
check(
|
|
|
|
r"
|
|
|
|
struct A {}
|
|
|
|
trait Trait { fn the_method(&self); }
|
|
|
|
impl<T> Trait for T {}
|
2021-01-06 20:15:48 +00:00
|
|
|
fn foo(a: &A) { a.$0 }
|
2020-07-04 10:36:12 +02:00
|
|
|
",
|
|
|
|
expect![[r#"
|
2021-07-05 16:44:44 +04:30
|
|
|
me the_method() (as Trait) fn(&self)
|
2020-07-04 10:36:12 +02:00
|
|
|
"#]],
|
2019-06-29 12:19:03 +02:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2020-03-14 20:48:36 +01:00
|
|
|
#[test]
|
|
|
|
fn completes_trait_method_from_other_module() {
|
2020-07-04 10:36:12 +02:00
|
|
|
check(
|
2019-01-07 19:12:19 +01:00
|
|
|
r"
|
2020-07-04 10:36:12 +02:00
|
|
|
struct A {}
|
|
|
|
mod m {
|
|
|
|
pub trait Trait { fn the_method(&self); }
|
|
|
|
}
|
|
|
|
use m::Trait;
|
|
|
|
impl Trait for A {}
|
2021-01-06 20:15:48 +00:00
|
|
|
fn foo(a: A) { a.$0 }
|
2020-07-04 10:36:12 +02:00
|
|
|
",
|
|
|
|
expect![[r#"
|
2021-07-05 16:44:44 +04:30
|
|
|
me the_method() (as Trait) fn(&self)
|
2020-07-04 10:36:12 +02:00
|
|
|
"#]],
|
2019-01-07 19:12:19 +01:00
|
|
|
);
|
|
|
|
}
|
2019-01-24 08:25:35 -05:00
|
|
|
|
2019-02-12 19:58:36 +02:00
|
|
|
#[test]
|
2020-07-04 10:36:12 +02:00
|
|
|
fn test_no_non_self_method() {
|
|
|
|
check(
|
|
|
|
r#"
|
|
|
|
struct A {}
|
|
|
|
impl A {
|
|
|
|
fn the_method() {}
|
|
|
|
}
|
|
|
|
fn foo(a: A) {
|
2021-01-06 20:15:48 +00:00
|
|
|
a.$0
|
2020-07-04 10:36:12 +02:00
|
|
|
}
|
|
|
|
"#,
|
2021-10-27 17:18:42 +02:00
|
|
|
expect![[r#""#]],
|
2019-02-12 19:58:36 +02:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2019-01-24 08:25:35 -05:00
|
|
|
#[test]
|
|
|
|
fn test_tuple_field_completion() {
|
2020-07-04 10:36:12 +02:00
|
|
|
check(
|
|
|
|
r#"
|
|
|
|
fn foo() {
|
|
|
|
let b = (0, 3.14);
|
2021-01-06 20:15:48 +00:00
|
|
|
b.$0
|
2020-07-04 10:36:12 +02:00
|
|
|
}
|
|
|
|
"#,
|
|
|
|
expect![[r#"
|
2021-10-27 17:18:42 +02:00
|
|
|
fd 0 i32
|
|
|
|
fd 1 f64
|
2020-07-04 10:36:12 +02:00
|
|
|
"#]],
|
2021-07-23 20:20:23 +02:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_tuple_struct_field_completion() {
|
|
|
|
check(
|
|
|
|
r#"
|
|
|
|
struct S(i32, f64);
|
|
|
|
fn foo() {
|
|
|
|
let b = S(0, 3.14);
|
|
|
|
b.$0
|
|
|
|
}
|
|
|
|
"#,
|
|
|
|
expect![[r#"
|
2021-10-27 17:18:42 +02:00
|
|
|
fd 0 i32
|
|
|
|
fd 1 f64
|
2021-07-23 20:20:23 +02:00
|
|
|
"#]],
|
|
|
|
);
|
2019-01-24 08:25:35 -05:00
|
|
|
}
|
2019-04-05 22:59:55 +02:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_tuple_field_inference() {
|
2020-07-04 10:36:12 +02:00
|
|
|
check(
|
|
|
|
r#"
|
|
|
|
pub struct S;
|
|
|
|
impl S { pub fn blah(&self) {} }
|
2019-04-05 22:59:55 +02:00
|
|
|
|
2020-07-04 10:36:12 +02:00
|
|
|
struct T(S);
|
2019-04-05 22:59:55 +02:00
|
|
|
|
2020-07-04 10:36:12 +02:00
|
|
|
impl T {
|
|
|
|
fn foo(&self) {
|
|
|
|
// FIXME: This doesn't work without the trailing `a` as `0.` is a float
|
2021-01-06 20:15:48 +00:00
|
|
|
self.0.a$0
|
2019-04-11 16:22:10 +03:00
|
|
|
}
|
2020-07-04 10:36:12 +02:00
|
|
|
}
|
|
|
|
"#,
|
|
|
|
expect![[r#"
|
2021-03-06 16:56:07 -08:00
|
|
|
me blah() fn(&self)
|
2020-07-04 10:36:12 +02:00
|
|
|
"#]],
|
2019-04-05 22:59:55 +02:00
|
|
|
);
|
|
|
|
}
|
2019-08-03 01:15:43 +07:00
|
|
|
|
2023-06-11 19:16:13 +09:00
|
|
|
#[test]
|
|
|
|
fn test_field_no_same_name() {
|
|
|
|
check(
|
|
|
|
r#"
|
|
|
|
//- minicore: deref
|
|
|
|
struct A { field: u8 }
|
|
|
|
struct B { field: u16, another: u32 }
|
|
|
|
impl core::ops::Deref for A {
|
|
|
|
type Target = B;
|
|
|
|
fn deref(&self) -> &Self::Target { loop {} }
|
|
|
|
}
|
|
|
|
fn test(a: A) {
|
|
|
|
a.$0
|
|
|
|
}
|
|
|
|
"#,
|
|
|
|
expect![[r#"
|
|
|
|
fd another u32
|
|
|
|
fd field u8
|
|
|
|
me deref() (use core::ops::Deref) fn(&self) -> &<Self as Deref>::Target
|
|
|
|
"#]],
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_tuple_field_no_same_index() {
|
|
|
|
check(
|
|
|
|
r#"
|
|
|
|
//- minicore: deref
|
|
|
|
struct A(u8);
|
|
|
|
struct B(u16, u32);
|
|
|
|
impl core::ops::Deref for A {
|
|
|
|
type Target = B;
|
|
|
|
fn deref(&self) -> &Self::Target { loop {} }
|
|
|
|
}
|
|
|
|
fn test(a: A) {
|
|
|
|
a.$0
|
|
|
|
}
|
|
|
|
"#,
|
|
|
|
expect![[r#"
|
|
|
|
fd 0 u8
|
|
|
|
fd 1 u32
|
|
|
|
me deref() (use core::ops::Deref) fn(&self) -> &<Self as Deref>::Target
|
|
|
|
"#]],
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2023-06-13 17:32:00 +09:00
|
|
|
#[test]
|
|
|
|
fn test_tuple_struct_deref_to_tuple_no_same_index() {
|
|
|
|
check(
|
|
|
|
r#"
|
|
|
|
//- minicore: deref
|
|
|
|
struct A(u8);
|
|
|
|
impl core::ops::Deref for A {
|
|
|
|
type Target = (u16, u32);
|
|
|
|
fn deref(&self) -> &Self::Target { loop {} }
|
|
|
|
}
|
|
|
|
fn test(a: A) {
|
|
|
|
a.$0
|
|
|
|
}
|
|
|
|
"#,
|
|
|
|
expect![[r#"
|
|
|
|
fd 0 u8
|
|
|
|
fd 1 u32
|
|
|
|
me deref() (use core::ops::Deref) fn(&self) -> &<Self as Deref>::Target
|
|
|
|
"#]],
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2019-08-03 01:15:43 +07:00
|
|
|
#[test]
|
2020-07-04 10:36:12 +02:00
|
|
|
fn test_completion_works_in_consts() {
|
|
|
|
check(
|
|
|
|
r#"
|
|
|
|
struct A { the_field: u32 }
|
|
|
|
const X: u32 = {
|
2021-01-06 20:15:48 +00:00
|
|
|
A { the_field: 92 }.$0
|
2020-07-04 10:36:12 +02:00
|
|
|
};
|
|
|
|
"#,
|
|
|
|
expect![[r#"
|
|
|
|
fd the_field u32
|
|
|
|
"#]],
|
2020-02-29 20:53:01 -08:00
|
|
|
);
|
|
|
|
}
|
2020-03-07 15:27:03 +01:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn works_in_simple_macro_1() {
|
2020-07-04 10:36:12 +02:00
|
|
|
check(
|
|
|
|
r#"
|
|
|
|
macro_rules! m { ($e:expr) => { $e } }
|
|
|
|
struct A { the_field: u32 }
|
|
|
|
fn foo(a: A) {
|
2021-01-06 20:15:48 +00:00
|
|
|
m!(a.x$0)
|
2020-07-04 10:36:12 +02:00
|
|
|
}
|
|
|
|
"#,
|
|
|
|
expect![[r#"
|
|
|
|
fd the_field u32
|
|
|
|
"#]],
|
2020-03-07 15:27:03 +01:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn works_in_simple_macro_2() {
|
|
|
|
// this doesn't work yet because the macro doesn't expand without the token -- maybe it can be fixed with better recovery
|
2020-07-04 10:36:12 +02:00
|
|
|
check(
|
|
|
|
r#"
|
|
|
|
macro_rules! m { ($e:expr) => { $e } }
|
|
|
|
struct A { the_field: u32 }
|
|
|
|
fn foo(a: A) {
|
2021-01-06 20:15:48 +00:00
|
|
|
m!(a.$0)
|
2020-07-04 10:36:12 +02:00
|
|
|
}
|
|
|
|
"#,
|
|
|
|
expect![[r#"
|
|
|
|
fd the_field u32
|
|
|
|
"#]],
|
2020-03-07 15:27:03 +01:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn works_in_simple_macro_recursive_1() {
|
2020-07-04 10:36:12 +02:00
|
|
|
check(
|
|
|
|
r#"
|
|
|
|
macro_rules! m { ($e:expr) => { $e } }
|
|
|
|
struct A { the_field: u32 }
|
|
|
|
fn foo(a: A) {
|
2021-01-06 20:15:48 +00:00
|
|
|
m!(m!(m!(a.x$0)))
|
2020-07-04 10:36:12 +02:00
|
|
|
}
|
|
|
|
"#,
|
|
|
|
expect![[r#"
|
|
|
|
fd the_field u32
|
|
|
|
"#]],
|
2020-03-07 15:27:03 +01:00
|
|
|
);
|
|
|
|
}
|
2020-03-10 20:56:26 +01:00
|
|
|
|
2020-03-13 13:03:31 +01:00
|
|
|
#[test]
|
|
|
|
fn macro_expansion_resilient() {
|
2020-07-04 10:36:12 +02:00
|
|
|
check(
|
|
|
|
r#"
|
2020-12-28 01:20:44 +08:00
|
|
|
macro_rules! d {
|
2020-07-04 10:36:12 +02:00
|
|
|
() => {};
|
|
|
|
($val:expr) => {
|
|
|
|
match $val { tmp => { tmp } }
|
|
|
|
};
|
|
|
|
// Trailing comma with single argument is ignored
|
2020-12-28 01:20:44 +08:00
|
|
|
($val:expr,) => { $crate::d!($val) };
|
2020-07-04 10:36:12 +02:00
|
|
|
($($val:expr),+ $(,)?) => {
|
2020-12-28 01:20:44 +08:00
|
|
|
($($crate::d!($val)),+,)
|
2020-07-04 10:36:12 +02:00
|
|
|
};
|
|
|
|
}
|
|
|
|
struct A { the_field: u32 }
|
|
|
|
fn foo(a: A) {
|
2020-12-28 01:20:44 +08:00
|
|
|
d!(a.$0)
|
2020-07-04 10:36:12 +02:00
|
|
|
}
|
|
|
|
"#,
|
|
|
|
expect![[r#"
|
|
|
|
fd the_field u32
|
|
|
|
"#]],
|
2020-03-13 13:03:31 +01:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2020-03-10 20:56:26 +01:00
|
|
|
#[test]
|
2020-07-04 10:36:12 +02:00
|
|
|
fn test_method_completion_issue_3547() {
|
|
|
|
check(
|
|
|
|
r#"
|
|
|
|
struct HashSet<T> {}
|
|
|
|
impl<T> HashSet<T> {
|
|
|
|
pub fn the_method(&self) {}
|
|
|
|
}
|
|
|
|
fn foo() {
|
|
|
|
let s: HashSet<_>;
|
2021-01-06 20:15:48 +00:00
|
|
|
s.$0
|
2020-07-04 10:36:12 +02:00
|
|
|
}
|
|
|
|
"#,
|
|
|
|
expect![[r#"
|
2021-03-06 16:56:07 -08:00
|
|
|
me the_method() fn(&self)
|
2020-07-04 10:36:12 +02:00
|
|
|
"#]],
|
2020-03-10 20:56:26 +01:00
|
|
|
);
|
|
|
|
}
|
2020-10-17 23:43:13 +02:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn completes_method_call_when_receiver_is_a_macro_call() {
|
|
|
|
check(
|
|
|
|
r#"
|
|
|
|
struct S;
|
|
|
|
impl S { fn foo(&self) {} }
|
|
|
|
macro_rules! make_s { () => { S }; }
|
2021-01-06 20:15:48 +00:00
|
|
|
fn main() { make_s!().f$0; }
|
2020-10-17 23:43:13 +02:00
|
|
|
"#,
|
|
|
|
expect![[r#"
|
2021-03-06 16:56:07 -08:00
|
|
|
me foo() fn(&self)
|
2020-10-17 23:43:13 +02:00
|
|
|
"#]],
|
|
|
|
)
|
|
|
|
}
|
2021-02-23 14:54:01 +01:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn completes_after_macro_call_in_submodule() {
|
|
|
|
check(
|
|
|
|
r#"
|
|
|
|
macro_rules! empty {
|
|
|
|
() => {};
|
|
|
|
}
|
|
|
|
|
|
|
|
mod foo {
|
|
|
|
#[derive(Debug, Default)]
|
|
|
|
struct Template2 {}
|
|
|
|
|
|
|
|
impl Template2 {
|
|
|
|
fn private(&self) {}
|
|
|
|
}
|
|
|
|
fn baz() {
|
|
|
|
let goo: Template2 = Template2 {};
|
|
|
|
empty!();
|
|
|
|
goo.$0
|
|
|
|
}
|
|
|
|
}
|
|
|
|
"#,
|
|
|
|
expect![[r#"
|
2021-03-06 16:56:07 -08:00
|
|
|
me private() fn(&self)
|
2021-02-23 14:54:01 +01:00
|
|
|
"#]],
|
|
|
|
);
|
|
|
|
}
|
2021-05-23 12:52:41 +02:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn issue_8931() {
|
|
|
|
check(
|
|
|
|
r#"
|
2021-06-18 22:14:39 +03:00
|
|
|
//- minicore: fn
|
2021-05-23 12:52:41 +02:00
|
|
|
struct S;
|
|
|
|
|
|
|
|
struct Foo;
|
|
|
|
impl Foo {
|
|
|
|
fn foo(&self) -> &[u8] { loop {} }
|
|
|
|
}
|
|
|
|
|
|
|
|
impl S {
|
|
|
|
fn indented(&mut self, f: impl FnOnce(&mut Self)) {
|
|
|
|
}
|
|
|
|
|
|
|
|
fn f(&mut self, v: Foo) {
|
|
|
|
self.indented(|this| v.$0)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
"#,
|
|
|
|
expect![[r#"
|
2021-05-23 13:00:14 +02:00
|
|
|
me foo() fn(&self) -> &[u8]
|
2021-05-23 12:52:41 +02:00
|
|
|
"#]],
|
|
|
|
);
|
|
|
|
}
|
2021-05-28 15:09:10 +02:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn completes_bare_fields_and_methods_in_methods() {
|
|
|
|
check(
|
|
|
|
r#"
|
|
|
|
struct Foo { field: i32 }
|
|
|
|
|
|
|
|
impl Foo { fn foo(&self) { $0 } }"#,
|
|
|
|
expect![[r#"
|
2022-02-03 16:05:21 +01:00
|
|
|
fd self.field i32
|
2021-05-28 15:09:10 +02:00
|
|
|
lc self &Foo
|
2023-12-08 13:19:34 +01:00
|
|
|
sp Self Foo
|
|
|
|
st Foo Foo
|
|
|
|
bt u32 u32
|
2022-05-05 10:49:43 +02:00
|
|
|
me self.foo() fn(&self)
|
2021-05-28 15:09:10 +02:00
|
|
|
"#]],
|
|
|
|
);
|
|
|
|
check(
|
|
|
|
r#"
|
|
|
|
struct Foo(i32);
|
|
|
|
|
|
|
|
impl Foo { fn foo(&mut self) { $0 } }"#,
|
|
|
|
expect![[r#"
|
2022-02-03 16:05:21 +01:00
|
|
|
fd self.0 i32
|
2021-05-28 15:09:10 +02:00
|
|
|
lc self &mut Foo
|
2023-12-08 13:19:34 +01:00
|
|
|
sp Self Foo
|
|
|
|
st Foo Foo
|
|
|
|
bt u32 u32
|
2022-05-05 10:49:43 +02:00
|
|
|
me self.foo() fn(&mut self)
|
2021-05-28 15:09:10 +02:00
|
|
|
"#]],
|
|
|
|
);
|
|
|
|
}
|
2021-09-06 00:16:12 +02:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn macro_completion_after_dot() {
|
|
|
|
check(
|
|
|
|
r#"
|
|
|
|
macro_rules! m {
|
|
|
|
($e:expr) => { $e };
|
|
|
|
}
|
|
|
|
|
|
|
|
struct Completable;
|
|
|
|
|
|
|
|
impl Completable {
|
|
|
|
fn method(&self) {}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn f() {
|
|
|
|
let c = Completable;
|
|
|
|
m!(c.$0);
|
|
|
|
}
|
|
|
|
"#,
|
|
|
|
expect![[r#"
|
|
|
|
me method() fn(&self)
|
|
|
|
"#]],
|
|
|
|
);
|
|
|
|
}
|
2021-09-27 21:44:27 +05:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn completes_method_call_when_receiver_type_has_errors_issue_10297() {
|
|
|
|
check(
|
|
|
|
r#"
|
|
|
|
//- minicore: iterator, sized
|
|
|
|
struct Vec<T>;
|
|
|
|
impl<T> IntoIterator for Vec<T> {
|
|
|
|
type Item = ();
|
|
|
|
type IntoIter = ();
|
|
|
|
fn into_iter(self);
|
|
|
|
}
|
|
|
|
fn main() {
|
|
|
|
let x: Vec<_>;
|
|
|
|
x.$0;
|
|
|
|
}
|
|
|
|
"#,
|
|
|
|
expect![[r#"
|
|
|
|
me into_iter() (as IntoIterator) fn(self) -> <Self as IntoIterator>::IntoIter
|
|
|
|
"#]],
|
|
|
|
)
|
|
|
|
}
|
2021-12-22 02:25:38 +01:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn postfix_drop_completion() {
|
|
|
|
cov_mark::check!(postfix_drop_completion);
|
|
|
|
check_edit(
|
|
|
|
"drop",
|
|
|
|
r#"
|
|
|
|
//- minicore: drop
|
|
|
|
struct Vec<T>(T);
|
|
|
|
impl<T> Drop for Vec<T> {
|
|
|
|
fn drop(&mut self) {}
|
|
|
|
}
|
|
|
|
fn main() {
|
|
|
|
let x = Vec(0u32)
|
|
|
|
x.$0;
|
|
|
|
}
|
|
|
|
"#,
|
|
|
|
r"
|
|
|
|
struct Vec<T>(T);
|
|
|
|
impl<T> Drop for Vec<T> {
|
|
|
|
fn drop(&mut self) {}
|
|
|
|
}
|
|
|
|
fn main() {
|
|
|
|
let x = Vec(0u32)
|
|
|
|
drop($0x);
|
|
|
|
}
|
|
|
|
",
|
|
|
|
)
|
|
|
|
}
|
2022-07-17 11:41:17 +05:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn issue_12484() {
|
|
|
|
check(
|
|
|
|
r#"
|
|
|
|
//- minicore: sized
|
|
|
|
trait SizeUser {
|
|
|
|
type Size;
|
|
|
|
}
|
|
|
|
trait Closure: SizeUser {}
|
|
|
|
trait Encrypt: SizeUser {
|
|
|
|
fn encrypt(self, _: impl Closure<Size = Self::Size>);
|
|
|
|
}
|
|
|
|
fn test(thing: impl Encrypt) {
|
|
|
|
thing.$0;
|
|
|
|
}
|
|
|
|
"#,
|
|
|
|
expect![[r#"
|
|
|
|
me encrypt(…) (as Encrypt) fn(self, impl Closure<Size = <Self as SizeUser>::Size>)
|
|
|
|
"#]],
|
|
|
|
)
|
|
|
|
}
|
2023-06-11 19:12:02 +09:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn only_consider_same_type_once() {
|
|
|
|
check(
|
|
|
|
r#"
|
|
|
|
//- minicore: deref
|
|
|
|
struct A(u8);
|
|
|
|
struct B(u16);
|
|
|
|
impl core::ops::Deref for A {
|
|
|
|
type Target = B;
|
|
|
|
fn deref(&self) -> &Self::Target { loop {} }
|
|
|
|
}
|
|
|
|
impl core::ops::Deref for B {
|
|
|
|
type Target = A;
|
|
|
|
fn deref(&self) -> &Self::Target { loop {} }
|
|
|
|
}
|
|
|
|
fn test(a: A) {
|
|
|
|
a.$0
|
|
|
|
}
|
|
|
|
"#,
|
|
|
|
expect![[r#"
|
|
|
|
fd 0 u8
|
|
|
|
me deref() (use core::ops::Deref) fn(&self) -> &<Self as Deref>::Target
|
|
|
|
"#]],
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn no_inference_var_in_completion() {
|
|
|
|
check(
|
|
|
|
r#"
|
|
|
|
struct S<T>(T);
|
|
|
|
fn test(s: S<Unknown>) {
|
|
|
|
s.$0
|
|
|
|
}
|
|
|
|
"#,
|
|
|
|
expect![[r#"
|
|
|
|
fd 0 {unknown}
|
|
|
|
"#]],
|
|
|
|
);
|
|
|
|
}
|
2023-11-02 22:37:50 +08:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn assoc_impl_1() {
|
|
|
|
check(
|
|
|
|
r#"
|
|
|
|
//- minicore: deref
|
|
|
|
fn main() {
|
|
|
|
let foo: Foo<&u8> = Foo::new(&42_u8);
|
|
|
|
foo.$0
|
|
|
|
}
|
|
|
|
|
|
|
|
trait Bar {
|
|
|
|
fn bar(&self);
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Bar for u8 {
|
|
|
|
fn bar(&self) {}
|
|
|
|
}
|
|
|
|
|
|
|
|
struct Foo<F> {
|
|
|
|
foo: F,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<F> Foo<F> {
|
|
|
|
fn new(foo: F) -> Foo<F> {
|
|
|
|
Foo { foo }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<F: core::ops::Deref<Target = impl Bar>> Foo<F> {
|
|
|
|
fn foobar(&self) {
|
|
|
|
self.foo.deref().bar()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
"#,
|
|
|
|
expect![[r#"
|
|
|
|
fd foo &u8
|
|
|
|
me foobar() fn(&self)
|
|
|
|
"#]],
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn assoc_impl_2() {
|
|
|
|
check(
|
|
|
|
r#"
|
|
|
|
//- minicore: deref
|
|
|
|
fn main() {
|
|
|
|
let foo: Foo<&u8> = Foo::new(&42_u8);
|
|
|
|
foo.$0
|
|
|
|
}
|
|
|
|
|
|
|
|
trait Bar {
|
|
|
|
fn bar(&self);
|
|
|
|
}
|
|
|
|
|
|
|
|
struct Foo<F> {
|
|
|
|
foo: F,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<F> Foo<F> {
|
|
|
|
fn new(foo: F) -> Foo<F> {
|
|
|
|
Foo { foo }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<B: Bar, F: core::ops::Deref<Target = B>> Foo<F> {
|
|
|
|
fn foobar(&self) {
|
|
|
|
self.foo.deref().bar()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
"#,
|
|
|
|
expect![[r#"
|
|
|
|
fd foo &u8
|
|
|
|
"#]],
|
|
|
|
);
|
|
|
|
}
|
2023-11-12 16:44:57 +05:30
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_struct_function_field_completion() {
|
|
|
|
check(
|
|
|
|
r#"
|
2023-11-22 23:59:45 +05:30
|
|
|
struct S { va_field: u32, fn_field: fn() }
|
|
|
|
fn foo() { S { va_field: 0, fn_field: || {} }.fi$0() }
|
2023-11-12 16:44:57 +05:30
|
|
|
"#,
|
|
|
|
expect![[r#"
|
2023-11-22 23:59:45 +05:30
|
|
|
fd fn_field fn()
|
2023-11-12 16:44:57 +05:30
|
|
|
"#]],
|
|
|
|
);
|
2023-11-22 23:59:45 +05:30
|
|
|
|
|
|
|
check_edit(
|
|
|
|
"fn_field",
|
|
|
|
r#"
|
|
|
|
struct S { va_field: u32, fn_field: fn() }
|
|
|
|
fn foo() { S { va_field: 0, fn_field: || {} }.fi$0() }
|
|
|
|
"#,
|
|
|
|
r#"
|
|
|
|
struct S { va_field: u32, fn_field: fn() }
|
2023-12-01 18:54:29 +05:30
|
|
|
fn foo() { (S { va_field: 0, fn_field: || {} }.fn_field)() }
|
2023-11-22 23:59:45 +05:30
|
|
|
"#,
|
|
|
|
);
|
2023-11-12 16:44:57 +05:30
|
|
|
}
|
2023-11-15 21:46:30 +05:30
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_tuple_function_field_completion() {
|
|
|
|
check(
|
|
|
|
r#"
|
|
|
|
struct B(u32, fn())
|
|
|
|
fn foo() {
|
|
|
|
let b = B(0, || {});
|
|
|
|
b.$0()
|
|
|
|
}
|
|
|
|
"#,
|
|
|
|
expect![[r#"
|
|
|
|
fd 1 fn()
|
|
|
|
"#]],
|
|
|
|
);
|
2023-11-22 23:59:45 +05:30
|
|
|
|
|
|
|
check_edit(
|
|
|
|
"1",
|
|
|
|
r#"
|
|
|
|
struct B(u32, fn())
|
|
|
|
fn foo() {
|
|
|
|
let b = B(0, || {});
|
|
|
|
b.$0()
|
|
|
|
}
|
|
|
|
"#,
|
|
|
|
r#"
|
|
|
|
struct B(u32, fn())
|
|
|
|
fn foo() {
|
|
|
|
let b = B(0, || {});
|
2023-12-01 18:54:29 +05:30
|
|
|
(b.1)()
|
2023-11-22 23:59:45 +05:30
|
|
|
}
|
|
|
|
"#,
|
|
|
|
)
|
2023-11-15 21:46:30 +05:30
|
|
|
}
|
2023-12-08 16:16:01 +05:30
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_fn_field_dot_access_method_has_parens_false() {
|
|
|
|
check(
|
|
|
|
r#"
|
|
|
|
struct Foo { baz: fn() }
|
|
|
|
impl Foo {
|
|
|
|
fn bar<T>(self, t: T): T { t }
|
|
|
|
}
|
|
|
|
|
|
|
|
fn baz() {
|
|
|
|
let foo = Foo{ baz: || {} };
|
|
|
|
foo.ba$0::<>;
|
|
|
|
}
|
|
|
|
"#,
|
|
|
|
expect![[r#"
|
|
|
|
me bar(…) fn(self, T)
|
|
|
|
"#]],
|
|
|
|
);
|
|
|
|
}
|
2019-01-08 22:33:36 +03:00
|
|
|
}
|