808 lines
18 KiB
Rust
Raw Normal View History

2021-01-06 20:15:48 +00:00
//! Completion of paths, i.e. `some::prefix::$0`.
use hir::{Adt, HasVisibility, PathResolution, ScopeDef};
2020-05-04 16:48:50 +02:00
use rustc_hash::FxHashSet;
2020-08-12 18:26:51 +02:00
use syntax::AstNode;
2019-01-27 17:23:49 +01:00
use crate::{CompletionContext, Completions};
2019-01-08 22:33:36 +03:00
2020-10-25 10:59:15 +03:00
pub(crate) fn complete_qualified_path(acc: &mut Completions, ctx: &CompletionContext) {
2020-08-13 22:41:55 +02:00
let path = match &ctx.path_qual {
2019-01-27 20:50:57 +01:00
Some(path) => path.clone(),
2020-05-04 16:48:50 +02:00
None => return,
2019-01-08 22:33:36 +03:00
};
2020-05-04 16:48:50 +02:00
2020-09-08 02:34:11 +03:00
if ctx.attribute_under_caret.is_some() || ctx.mod_declaration_under_caret.is_some() {
2020-05-04 16:48:50 +02:00
return;
}
2020-07-11 01:26:24 +02:00
let context_module = ctx.scope.module();
2020-08-13 22:41:55 +02:00
let resolution = match ctx.sema.resolve_path(&path) {
2020-04-30 00:10:15 +02:00
Some(res) => res,
None => return,
2019-01-08 22:33:36 +03:00
};
// Add associated types on type parameters and `Self`.
2020-07-11 01:26:24 +02:00
resolution.assoc_type_shorthand_candidates(ctx.db, |alias| {
acc.add_type_alias(ctx, alias);
None::<()>
});
2020-07-11 01:26:24 +02:00
match resolution {
PathResolution::Def(hir::ModuleDef::Module(module)) => {
let module_scope = module.scope(ctx.db, context_module);
2019-12-21 15:17:10 +01:00
for (name, def) in module_scope {
if ctx.use_item_syntax.is_some() {
if let ScopeDef::Unknown = def {
if let Some(name_ref) = ctx.name_ref_syntax.as_ref() {
2020-01-13 11:27:06 -05:00
if name_ref.syntax().text() == name.to_string().as_str() {
2021-01-06 20:15:48 +00:00
// for `use self::foo$0`, don't suggest `foo` as a completion
2021-03-08 22:19:44 +02:00
cov_mark::hit!(dont_complete_current_use);
2019-04-02 17:58:04 +03:00
continue;
}
}
}
}
2019-12-21 15:17:10 +01:00
2019-10-31 18:45:10 +03:00
acc.add_resolution(ctx, name.to_string(), &def);
}
2019-01-08 22:33:36 +03:00
}
PathResolution::Def(def @ hir::ModuleDef::Adt(_))
2021-02-11 19:52:46 +01:00
| PathResolution::Def(def @ hir::ModuleDef::TypeAlias(_))
| PathResolution::Def(def @ hir::ModuleDef::BuiltinType(_)) => {
2019-09-13 00:34:52 +03:00
if let hir::ModuleDef::Adt(Adt::Enum(e)) = def {
for variant in e.variants(ctx.db) {
2020-04-03 19:33:12 +02:00
acc.add_enum_variant(ctx, variant, None);
}
2019-02-24 20:56:19 +03:00
}
let ty = match def {
2019-09-13 00:34:52 +03:00
hir::ModuleDef::Adt(adt) => adt.ty(ctx.db),
2019-07-03 03:08:39 +09:00
hir::ModuleDef::TypeAlias(a) => a.ty(ctx.db),
2021-02-11 19:52:46 +01:00
hir::ModuleDef::BuiltinType(builtin) => {
let module = match ctx.scope.module() {
Some(it) => it,
None => return,
};
builtin.ty(ctx.db, module)
}
_ => unreachable!(),
};
// XXX: For parity with Rust bug #22519, this does not complete Ty::AssocType.
// (where AssocType is defined on a trait, not an inherent impl)
let krate = ctx.krate;
2019-10-31 21:21:48 +01:00
if let Some(krate) = krate {
2020-07-11 01:26:24 +02:00
let traits_in_scope = ctx.scope.traits_in_scope();
2020-01-14 14:42:52 +01:00
ty.iterate_path_candidates(ctx.db, krate, &traits_in_scope, None, |_ty, item| {
if context_module.map_or(false, |m| !item.is_visible_from(ctx.db, m)) {
return None;
}
2020-01-14 14:42:52 +01:00
match item {
2021-03-03 21:59:41 +01:00
hir::AssocItem::Function(func) => acc.add_function(ctx, func, None),
2020-01-14 14:42:52 +01:00
hir::AssocItem::Const(ct) => acc.add_const(ctx, ct),
hir::AssocItem::TypeAlias(ty) => acc.add_type_alias(ctx, ty),
}
None::<()>
});
// Iterate assoc types separately
2020-05-05 23:56:10 +08:00
ty.iterate_assoc_items(ctx.db, krate, |item| {
if context_module.map_or(false, |m| !item.is_visible_from(ctx.db, m)) {
return None;
}
2019-10-31 21:21:48 +01:00
match item {
hir::AssocItem::Function(_) | hir::AssocItem::Const(_) => {}
hir::AssocItem::TypeAlias(ty) => acc.add_type_alias(ctx, ty),
}
None::<()>
2019-04-15 00:03:54 +02:00
});
}
}
PathResolution::Def(hir::ModuleDef::Trait(t)) => {
// Handles `Trait::assoc` as well as `<Ty as Trait>::assoc`.
2019-11-01 00:15:15 +01:00
for item in t.items(ctx.db) {
if context_module.map_or(false, |m| !item.is_visible_from(ctx.db, m)) {
continue;
}
2019-11-01 00:15:15 +01:00
match item {
2021-03-03 21:59:41 +01:00
hir::AssocItem::Function(func) => acc.add_function(ctx, func, None),
2019-11-01 00:15:15 +01:00
hir::AssocItem::Const(ct) => acc.add_const(ctx, ct),
hir::AssocItem::TypeAlias(ty) => acc.add_type_alias(ctx, ty),
}
}
}
PathResolution::TypeParam(_) | PathResolution::SelfType(_) => {
if let Some(krate) = ctx.krate {
2020-07-11 01:26:24 +02:00
let ty = match resolution {
PathResolution::TypeParam(param) => param.ty(ctx.db),
2021-03-29 17:46:33 +02:00
PathResolution::SelfType(impl_def) => impl_def.self_ty(ctx.db),
_ => return,
};
if let Some(Adt::Enum(e)) = ty.as_adt() {
for variant in e.variants(ctx.db) {
acc.add_enum_variant(ctx, variant, None);
}
}
2020-07-11 01:26:24 +02:00
let traits_in_scope = ctx.scope.traits_in_scope();
let mut seen = FxHashSet::default();
ty.iterate_path_candidates(ctx.db, krate, &traits_in_scope, None, |_ty, item| {
if context_module.map_or(false, |m| !item.is_visible_from(ctx.db, m)) {
return None;
}
// We might iterate candidates of a trait multiple times here, so deduplicate
// them.
if seen.insert(item) {
match item {
2021-03-03 21:59:41 +01:00
hir::AssocItem::Function(func) => acc.add_function(ctx, func, None),
hir::AssocItem::Const(ct) => acc.add_const(ctx, ct),
hir::AssocItem::TypeAlias(ty) => acc.add_type_alias(ctx, ty),
}
}
None::<()>
});
}
}
2019-10-30 13:36:37 -04: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};
2019-01-08 22:33:36 +03:00
use crate::{
2020-07-04 18:53:30 +02:00
test_utils::{check_edit, completion_list},
CompletionKind,
};
fn check(ra_fixture: &str, expect: Expect) {
let actual = completion_list(ra_fixture, CompletionKind::Reference);
expect.assert_eq(&actual);
}
2019-02-24 21:54:13 +03:00
2020-07-04 18:53:30 +02:00
fn check_builtin(ra_fixture: &str, expect: Expect) {
let actual = completion_list(ra_fixture, CompletionKind::BuiltinType);
expect.assert_eq(&actual);
2019-01-08 22:33:36 +03:00
}
2019-02-01 23:06:57 +01:00
#[test]
fn dont_complete_current_use() {
2021-03-08 22:19:44 +02:00
cov_mark::check!(dont_complete_current_use);
2021-01-06 20:15:48 +00:00
check(r#"use self::foo$0;"#, expect![[""]]);
2019-02-01 23:06:57 +01:00
}
#[test]
fn dont_complete_current_use_in_braces_with_glob() {
2020-07-04 18:53:30 +02:00
check(
r#"
mod foo { pub struct S; }
2021-01-06 20:15:48 +00:00
use self::{foo::*, bar$0};
2020-07-04 18:53:30 +02:00
"#,
expect![[r#"
st S
md foo
"#]],
);
}
2019-05-30 16:10:07 +03:00
#[test]
fn dont_complete_primitive_in_use() {
2021-01-06 20:15:48 +00:00
check_builtin(r#"use self::$0;"#, expect![[""]]);
2019-05-30 16:10:07 +03:00
}
#[test]
fn dont_complete_primitive_in_module_scope() {
2021-01-06 20:15:48 +00:00
check_builtin(r#"fn foo() { self::$0 }"#, expect![[""]]);
}
2019-05-30 16:10:07 +03:00
#[test]
fn completes_primitives() {
2020-07-04 18:53:30 +02:00
check_builtin(
2021-01-06 20:15:48 +00:00
r#"fn main() { let _: $0 = 92; }"#,
2020-07-04 18:53:30 +02:00
expect![[r#"
bt u32
2020-07-04 18:53:30 +02:00
bt bool
bt u8
bt isize
bt u16
bt u64
bt u128
2020-07-04 18:53:30 +02:00
bt f32
bt i128
bt i16
bt str
2020-07-04 18:53:30 +02:00
bt i64
bt char
bt f64
bt i32
2020-07-04 18:53:30 +02:00
bt i8
bt usize
"#]],
2019-01-25 12:51:36 -05:00
);
}
#[test]
fn completes_mod_with_same_name_as_function() {
2020-07-04 18:53:30 +02:00
check(
r#"
2021-01-06 20:15:48 +00:00
use self::my::$0;
2020-07-04 18:53:30 +02:00
mod my { pub struct Bar; }
fn my() {}
"#,
expect![[r#"
st Bar
"#]],
);
}
#[test]
2020-07-04 18:53:30 +02:00
fn filters_visibility() {
check(
r#"
2021-01-06 20:15:48 +00:00
use self::my::$0;
2020-07-04 18:53:30 +02:00
mod my {
struct Bar;
pub struct Foo;
pub use Bar as PublicBar;
}
"#,
expect![[r#"
st Foo
st PublicBar
"#]],
);
}
2019-01-08 22:33:36 +03:00
#[test]
fn completes_use_item_starting_with_self() {
2020-07-04 18:53:30 +02:00
check(
r#"
2021-01-06 20:15:48 +00:00
use self::m::$0;
2019-01-08 22:33:36 +03:00
2020-07-04 18:53:30 +02:00
mod m { pub struct Bar; }
"#,
expect![[r#"
st Bar
"#]],
2019-01-08 22:33:36 +03:00
);
}
#[test]
fn completes_use_item_starting_with_crate() {
2020-07-04 18:53:30 +02:00
check(
r#"
//- /lib.rs
mod foo;
struct Spam;
//- /foo.rs
2021-01-06 20:15:48 +00:00
use crate::Sp$0
2020-07-04 18:53:30 +02:00
"#,
expect![[r#"
md foo
st Spam
2020-07-04 18:53:30 +02:00
"#]],
2019-01-08 22:33:36 +03:00
);
}
#[test]
fn completes_nested_use_tree() {
2020-07-04 18:53:30 +02:00
check(
r#"
//- /lib.rs
mod foo;
struct Spam;
//- /foo.rs
2021-01-06 20:15:48 +00:00
use crate::{Sp$0};
2020-07-04 18:53:30 +02:00
"#,
expect![[r#"
md foo
st Spam
2020-07-04 18:53:30 +02:00
"#]],
2019-01-08 22:33:36 +03:00
);
}
#[test]
fn completes_deeply_nested_use_tree() {
2020-07-04 18:53:30 +02:00
check(
r#"
//- /lib.rs
mod foo;
pub mod bar {
pub mod baz {
pub struct Spam;
2019-01-25 11:50:59 -05:00
}
2020-07-04 18:53:30 +02:00
}
//- /foo.rs
2021-01-06 20:15:48 +00:00
use crate::{bar::{baz::Sp$0}};
2020-07-04 18:53:30 +02:00
"#,
expect![[r#"
st Spam
"#]],
);
}
#[test]
2020-07-04 18:53:30 +02:00
fn completes_enum_variant() {
check(
r#"
enum E { Foo, Bar(i32) }
2021-01-06 20:15:48 +00:00
fn foo() { let _ = E::$0 }
2020-07-04 18:53:30 +02:00
"#,
expect![[r#"
2020-07-04 19:03:58 +02:00
ev Foo ()
ev Bar() (i32)
2020-07-04 18:53:30 +02:00
"#]],
);
}
#[test]
2020-07-04 18:53:30 +02:00
fn completes_struct_associated_items() {
check(
r#"
//- /lib.rs
struct S;
impl S {
fn a() {}
fn b(&self) {}
const C: i32 = 42;
type T = i32;
}
2021-01-06 20:15:48 +00:00
fn foo() { let _ = S::$0 }
2020-07-04 18:53:30 +02:00
"#,
expect![[r#"
fn a() fn()
me b() fn(&self)
ct C const C: i32 = 42;
ta T type T = i32;
2020-07-04 18:53:30 +02:00
"#]],
);
}
#[test]
2020-07-04 18:53:30 +02:00
fn associated_item_visibility() {
check(
r#"
struct S;
2020-07-04 18:53:30 +02:00
mod m {
impl super::S {
2020-10-25 10:59:15 +03:00
pub(crate) fn public_method() { }
2020-07-04 18:53:30 +02:00
fn private_method() { }
2020-10-25 10:59:15 +03:00
pub(crate) type PublicType = u32;
2020-07-04 18:53:30 +02:00
type PrivateType = u32;
2020-10-25 10:59:15 +03:00
pub(crate) const PUBLIC_CONST: u32 = 1;
2020-07-04 18:53:30 +02:00
const PRIVATE_CONST: u32 = 1;
}
2020-07-04 18:53:30 +02:00
}
2021-01-06 20:15:48 +00:00
fn foo() { let _ = S::$0 }
2020-07-04 18:53:30 +02:00
"#,
expect![[r#"
fn public_method() fn()
2020-10-25 10:59:15 +03:00
ct PUBLIC_CONST pub(crate) const PUBLIC_CONST: u32 = 1;
ta PublicType pub(crate) type PublicType = u32;
2020-07-04 18:53:30 +02:00
"#]],
);
}
#[test]
fn completes_enum_associated_method() {
2020-07-04 18:53:30 +02:00
check(
r#"
enum E {};
impl E { fn m() { } }
2021-01-06 20:15:48 +00:00
fn foo() { let _ = E::$0 }
2020-07-04 18:53:30 +02:00
"#,
expect![[r#"
fn m() fn()
2020-07-04 18:53:30 +02:00
"#]],
);
}
#[test]
fn completes_union_associated_method() {
2020-07-04 18:53:30 +02:00
check(
r#"
union U {};
impl U { fn m() { } }
2021-01-06 20:15:48 +00:00
fn foo() { let _ = U::$0 }
2020-07-04 18:53:30 +02:00
"#,
expect![[r#"
fn m() fn()
2020-07-04 18:53:30 +02:00
"#]],
);
}
#[test]
fn completes_use_paths_across_crates() {
2020-07-04 18:53:30 +02:00
check(
r#"
2020-10-02 16:13:48 +02:00
//- /main.rs crate:main deps:foo
2021-01-06 20:15:48 +00:00
use foo::$0;
2020-07-04 18:53:30 +02:00
2020-10-02 16:13:48 +02:00
//- /foo/lib.rs crate:foo
2020-07-04 18:53:30 +02:00
pub mod bar { pub struct S; }
"#,
expect![[r#"
md bar
"#]],
);
}
#[test]
fn completes_trait_associated_method_1() {
2020-07-04 18:53:30 +02:00
check(
r#"
trait Trait { fn m(); }
2021-01-06 20:15:48 +00:00
fn foo() { let _ = Trait::$0 }
2020-07-04 18:53:30 +02:00
"#,
expect![[r#"
fn m() fn()
2020-07-04 18:53:30 +02:00
"#]],
);
}
#[test]
fn completes_trait_associated_method_2() {
2020-07-04 18:53:30 +02:00
check(
r#"
trait Trait { fn m(); }
struct S;
impl Trait for S {}
2021-01-06 20:15:48 +00:00
fn foo() { let _ = S::$0 }
2020-07-04 18:53:30 +02:00
"#,
expect![[r#"
fn m() fn()
2020-07-04 18:53:30 +02:00
"#]],
);
}
#[test]
fn completes_trait_associated_method_3() {
2020-07-04 18:53:30 +02:00
check(
r#"
trait Trait { fn m(); }
2020-07-04 18:53:30 +02:00
struct S;
impl Trait for S {}
2021-01-06 20:15:48 +00:00
fn foo() { let _ = <S as Trait>::$0 }
2020-07-04 18:53:30 +02:00
"#,
expect![[r#"
fn m() fn()
2020-07-04 18:53:30 +02:00
"#]],
2019-07-03 03:08:39 +09:00
);
}
#[test]
fn completes_ty_param_assoc_ty() {
2020-07-04 18:53:30 +02:00
check(
r#"
trait Super {
type Ty;
const CONST: u8;
fn func() {}
fn method(&self) {}
}
2020-07-04 18:53:30 +02:00
trait Sub: Super {
type SubTy;
const C2: ();
fn subfunc() {}
fn submethod(&self) {}
}
2021-01-06 20:15:48 +00:00
fn foo<T: Sub>() { T::$0 }
2020-07-04 18:53:30 +02:00
"#,
expect![[r#"
ta SubTy type SubTy;
ta Ty type Ty;
ct C2 const C2: ();
fn subfunc() fn()
me submethod() fn(&self)
ct CONST const CONST: u8;
fn func() fn()
me method() fn(&self)
2020-07-04 18:53:30 +02:00
"#]],
);
}
#[test]
fn completes_self_param_assoc_ty() {
2020-07-04 18:53:30 +02:00
check(
r#"
trait Super {
type Ty;
const CONST: u8 = 0;
fn func() {}
fn method(&self) {}
}
2020-07-04 18:53:30 +02:00
trait Sub: Super {
type SubTy;
const C2: () = ();
fn subfunc() {}
fn submethod(&self) {}
}
2020-07-04 18:53:30 +02:00
struct Wrap<T>(T);
impl<T> Super for Wrap<T> {}
impl<T> Sub for Wrap<T> {
fn subfunc() {
// Should be able to assume `Self: Sub + Super`
2021-01-06 20:15:48 +00:00
Self::$0
2020-07-04 18:53:30 +02:00
}
}
"#,
expect![[r#"
ta SubTy type SubTy;
ta Ty type Ty;
ct CONST const CONST: u8 = 0;
fn func() fn()
me method() fn(&self)
ct C2 const C2: () = ();
fn subfunc() fn()
me submethod() fn(&self)
2020-07-04 18:53:30 +02:00
"#]],
);
}
2019-07-03 03:08:39 +09:00
#[test]
fn completes_type_alias() {
2020-07-04 18:53:30 +02:00
check(
r#"
struct S;
impl S { fn foo() {} }
type T = S;
impl T { fn bar() {} }
2021-01-06 20:15:48 +00:00
fn main() { T::$0; }
2020-07-04 18:53:30 +02:00
"#,
expect![[r#"
fn foo() fn()
fn bar() fn()
2020-07-04 18:53:30 +02:00
"#]],
2019-09-10 13:32:47 +08:00
);
}
#[test]
2019-09-11 22:39:02 +08:00
fn completes_qualified_macros() {
2020-07-04 18:53:30 +02:00
check(
r#"
#[macro_export]
macro_rules! foo { () => {} }
2021-01-06 20:15:48 +00:00
fn main() { let _ = crate::$0 }
2020-07-04 18:53:30 +02:00
"#,
expect![[r##"
fn main() fn()
ma foo!() #[macro_export] macro_rules! foo
2020-07-04 18:53:30 +02:00
"##]],
);
}
2020-07-04 10:36:12 +02:00
#[test]
fn test_super_super_completion() {
2020-07-04 18:53:30 +02:00
check(
r#"
mod a {
const A: usize = 0;
mod b {
const B: usize = 0;
2021-01-06 20:15:48 +00:00
mod c { use super::super::$0 }
2020-07-04 18:53:30 +02:00
}
}
"#,
expect![[r#"
md b
ct A
2020-07-04 18:53:30 +02:00
"#]],
2020-07-04 10:36:12 +02:00
);
}
#[test]
fn completes_reexported_items_under_correct_name() {
2020-07-04 18:53:30 +02:00
check(
r#"
2021-01-06 20:15:48 +00:00
fn foo() { self::m::$0 }
2020-07-04 18:53:30 +02:00
mod m {
pub use super::p::wrong_fn as right_fn;
pub use super::p::WRONG_CONST as RIGHT_CONST;
pub use super::p::WrongType as RightType;
}
mod p {
fn wrong_fn() {}
const WRONG_CONST: u32 = 1;
struct WrongType {};
}
"#,
expect![[r#"
ct RIGHT_CONST
fn right_fn() fn()
st RightType
2020-07-04 18:53:30 +02:00
"#]],
);
check_edit(
"RightType",
r#"
2021-01-06 20:15:48 +00:00
fn foo() { self::m::$0 }
2020-07-04 18:53:30 +02:00
mod m {
pub use super::p::wrong_fn as right_fn;
pub use super::p::WRONG_CONST as RIGHT_CONST;
pub use super::p::WrongType as RightType;
}
mod p {
fn wrong_fn() {}
const WRONG_CONST: u32 = 1;
struct WrongType {};
}
"#,
r#"
fn foo() { self::m::RightType }
mod m {
pub use super::p::wrong_fn as right_fn;
pub use super::p::WRONG_CONST as RIGHT_CONST;
pub use super::p::WrongType as RightType;
}
mod p {
fn wrong_fn() {}
const WRONG_CONST: u32 = 1;
struct WrongType {};
}
"#,
);
}
2020-03-07 15:47:10 +01:00
#[test]
fn completes_in_simple_macro_call() {
2020-07-04 18:53:30 +02:00
check(
2020-03-07 15:47:10 +01:00
r#"
2020-07-04 18:53:30 +02:00
macro_rules! m { ($e:expr) => { $e } }
2021-01-06 20:15:48 +00:00
fn main() { m!(self::f$0); }
2020-07-04 18:53:30 +02:00
fn foo() {}
"#,
expect![[r#"
fn main() fn()
fn foo() fn()
2020-07-04 18:53:30 +02:00
"#]],
2020-03-07 15:47:10 +01:00
);
}
2020-03-10 19:58:17 -07:00
#[test]
fn function_mod_share_name() {
2020-07-04 18:53:30 +02:00
check(
r#"
2021-01-06 20:15:48 +00:00
fn foo() { self::m::$0 }
2020-03-10 19:58:17 -07:00
2020-07-04 18:53:30 +02:00
mod m {
pub mod z {}
pub fn z() {}
}
"#,
expect![[r#"
md z
fn z() fn()
2020-07-04 18:53:30 +02:00
"#]],
2020-03-10 19:58:17 -07:00
);
}
#[test]
fn completes_hashmap_new() {
2020-07-04 18:53:30 +02:00
check(
r#"
struct RandomState;
struct HashMap<K, V, S = RandomState> {}
impl<K, V> HashMap<K, V, RandomState> {
pub fn new() -> HashMap<K, V, RandomState> { }
}
fn foo() {
2021-01-06 20:15:48 +00:00
HashMap::$0
2020-07-04 18:53:30 +02:00
}
"#,
expect![[r#"
fn new() fn() -> HashMap<K, V, RandomState>
2020-07-04 18:53:30 +02:00
"#]],
);
}
2020-05-04 16:48:50 +02:00
#[test]
fn dont_complete_attr() {
2020-07-04 18:53:30 +02:00
check(
r#"
mod foo { pub struct Foo; }
2021-01-06 20:15:48 +00:00
#[foo::$0]
2020-07-04 18:53:30 +02:00
fn f() {}
"#,
expect![[""]],
);
2020-05-04 16:48:50 +02:00
}
#[test]
fn completes_function() {
check(
r#"
fn foo(
a: i32,
b: i32
) {
}
fn main() {
2021-01-06 20:15:48 +00:00
fo$0
}
"#,
expect![[r#"
fn main() fn()
fn foo() fn(i32, i32)
"#]],
);
}
#[test]
fn completes_self_enum() {
check(
r#"
enum Foo {
Bar,
Baz,
}
impl Foo {
fn foo(self) {
2021-01-06 20:15:48 +00:00
Self::$0
}
}
"#,
expect![[r#"
ev Bar ()
ev Baz ()
me foo() fn(self)
"#]],
);
}
2021-02-11 19:52:46 +01:00
#[test]
fn completes_primitive_assoc_const() {
check(
r#"
//- /lib.rs crate:lib deps:core
fn f() {
u8::$0
}
//- /core.rs crate:core
#[lang = "u8"]
impl u8 {
pub const MAX: Self = 255;
pub fn func(self) {}
}
"#,
expect![[r#"
ct MAX pub const MAX: Self = 255;
me func() fn(self)
2021-02-11 19:52:46 +01:00
"#]],
);
}
2019-01-08 22:33:36 +03:00
}