rust/crates/ide_completion/src/completions/unqualified_path.rs

716 lines
13 KiB
Rust
Raw Normal View History

2020-03-07 15:27:03 +01:00
//! Completion of names from the current scope, e.g. locals and imported items.
use hir::ScopeDef;
use crate::{CompletionContext, Completions};
2019-01-08 22:33:36 +03:00
2020-10-25 10:59:15 +03:00
pub(crate) fn complete_unqualified_path(acc: &mut Completions, ctx: &CompletionContext) {
if !ctx.is_trivial_path {
2020-05-04 16:48:50 +02:00
return;
}
2021-05-27 21:12:50 +02:00
if ctx.is_path_disallowed() || ctx.expects_item() {
2019-09-06 21:57:11 +03:00
return;
}
2021-05-27 21:12:50 +02:00
if ctx.expects_assoc_item() {
ctx.scope.process_all_names(&mut |name, def| {
if let ScopeDef::MacroDef(macro_def) = def {
acc.add_macro(ctx, Some(name.clone()), macro_def);
}
2021-05-27 20:53:38 +02:00
if let ScopeDef::ModuleDef(hir::ModuleDef::Module(_)) = def {
acc.add_resolution(ctx, name, &def);
2021-05-27 20:53:38 +02:00
}
});
return;
}
2019-09-06 21:57:11 +03:00
if ctx.expects_use_tree() {
cov_mark::hit!(only_completes_modules_in_import);
ctx.scope.process_all_names(&mut |name, res| {
if let ScopeDef::ModuleDef(hir::ModuleDef::Module(_)) = res {
acc.add_resolution(ctx, name, &res);
}
});
return;
}
2021-05-05 22:55:12 +02:00
if let Some(hir::Adt::Enum(e)) =
ctx.expected_type.as_ref().and_then(|ty| ty.strip_references().as_adt())
{
super::complete_enum_variants(acc, ctx, e, |acc, ctx, variant, path| {
acc.add_qualified_enum_variant(ctx, variant, path)
});
}
2020-07-11 01:26:24 +02:00
ctx.scope.process_all_names(&mut |name, res| {
2021-01-19 20:01:49 +01:00
if let ScopeDef::GenericParam(hir::GenericParam::LifetimeParam(_)) = res {
2021-03-08 22:19:44 +02:00
cov_mark::hit!(skip_lifetime_completion);
2021-01-19 20:01:49 +01:00
return;
}
acc.add_resolution(ctx, name, &res);
});
}
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::{
test_utils::{check_edit, completion_list_with_config, TEST_CONFIG},
2020-12-04 21:23:30 +02:00
CompletionConfig, CompletionKind,
};
fn check(ra_fixture: &str, expect: Expect) {
check_with_config(TEST_CONFIG, ra_fixture, expect);
}
fn check_with_config(config: CompletionConfig, ra_fixture: &str, expect: Expect) {
let actual = completion_list_with_config(config, ra_fixture, CompletionKind::Reference);
expect.assert_eq(&actual)
2019-01-08 22:33:36 +03:00
}
#[test]
fn only_completes_modules_in_import() {
cov_mark::check!(only_completes_modules_in_import);
check(
r#"
use f$0
struct Foo;
mod foo {}
"#,
expect![[r#"
md foo
"#]],
);
}
#[test]
fn bind_pat_and_path_ignore_at() {
check(
r#"
enum Enum { A, B }
fn quux(x: Option<Enum>) {
match x {
None => (),
2021-01-06 20:15:48 +00:00
Some(en$0 @ Enum::A) => (),
}
}
"#,
expect![[r#""#]],
);
}
#[test]
fn bind_pat_and_path_ignore_ref() {
check(
r#"
enum Enum { A, B }
fn quux(x: Option<Enum>) {
match x {
None => (),
2021-01-06 20:15:48 +00:00
Some(ref en$0) => (),
}
}
"#,
expect![[r#""#]],
);
}
#[test]
fn bind_pat_and_path() {
check(
r#"
enum Enum { A, B }
fn quux(x: Option<Enum>) {
match x {
None => (),
2021-01-06 20:15:48 +00:00
Some(En$0) => (),
}
}
"#,
expect![[r#"
en Enum
"#]],
);
}
2019-01-08 22:33:36 +03:00
#[test]
fn completes_bindings_from_let() {
check(
r#"
fn quux(x: i32) {
let y = 92;
2021-01-06 20:15:48 +00:00
1 + $0;
let z = ();
}
"#,
expect![[r#"
2021-01-20 18:46:14 +01:00
lc y i32
lc x i32
fn quux() fn(i32)
"#]],
);
2019-01-08 22:33:36 +03:00
}
#[test]
fn completes_bindings_from_if_let() {
check(
r#"
fn quux() {
if let Some(x) = foo() {
let y = 92;
};
if let Some(a) = bar() {
let b = 62;
2021-01-06 20:15:48 +00:00
1 + $0
}
}
"#,
expect![[r#"
2021-01-20 18:46:14 +01:00
lc b i32
lc a
fn quux() fn()
"#]],
);
2019-01-08 22:33:36 +03:00
}
#[test]
fn completes_bindings_from_for() {
check(
r#"
fn quux() {
2021-01-06 20:15:48 +00:00
for x in &[1, 2, 3] { $0 }
}
"#,
expect![[r#"
2021-01-20 18:46:14 +01:00
lc x
fn quux() fn()
"#]],
);
2019-01-08 22:33:36 +03:00
}
#[test]
fn completes_if_prefix_is_keyword() {
2021-03-08 22:19:44 +02:00
cov_mark::check!(completes_if_prefix_is_keyword);
check_edit(
"wherewolf",
r#"
fn main() {
let wherewolf = 92;
2021-01-06 20:15:48 +00:00
drop(where$0)
}
"#,
r#"
fn main() {
let wherewolf = 92;
drop(wherewolf)
}
"#,
)
}
2019-02-01 23:06:57 +01:00
#[test]
fn completes_generic_params() {
check(
2021-01-06 20:15:48 +00:00
r#"fn quux<T>() { $0 }"#,
expect![[r#"
tp T
fn quux() fn()
"#]],
);
2021-01-19 20:01:49 +01:00
check(
r#"fn quux<const C: usize>() { $0 }"#,
expect![[r#"
cp C
fn quux() fn()
2021-01-19 20:01:49 +01:00
"#]],
);
}
#[test]
fn does_not_complete_lifetimes() {
2021-03-08 22:19:44 +02:00
cov_mark::check!(skip_lifetime_completion);
2021-01-19 20:01:49 +01:00
check(
r#"fn quux<'a>() { $0 }"#,
expect![[r#"
fn quux() fn()
2021-01-19 20:01:49 +01:00
"#]],
);
2019-02-01 23:06:57 +01:00
}
#[test]
fn completes_generic_params_in_struct() {
check(
2021-01-06 20:15:48 +00:00
r#"struct S<T> { x: $0}"#,
expect![[r#"
2021-01-20 18:46:14 +01:00
sp Self
tp T
st S<>
"#]],
);
2019-02-01 23:06:57 +01:00
}
2019-01-08 22:33:36 +03:00
#[test]
fn completes_self_in_enum() {
check(
2021-01-06 20:15:48 +00:00
r#"enum X { Y($0) }"#,
expect![[r#"
2021-01-20 18:46:14 +01:00
sp Self
en X
"#]],
);
}
#[test]
2019-01-08 22:33:36 +03:00
fn completes_module_items() {
check(
r#"
struct S;
enum E {}
2021-01-06 20:15:48 +00:00
fn quux() { $0 }
"#,
expect![[r#"
st S
fn quux() fn()
en E
"#]],
);
2019-01-08 22:33:36 +03:00
}
/// Regression test for issue #6091.
#[test]
fn correctly_completes_module_items_prefixed_with_underscore() {
check_edit(
"_alpha",
r#"
fn main() {
2021-01-06 20:15:48 +00:00
_$0
}
fn _alpha() {}
"#,
r#"
fn main() {
_alpha()$0
}
fn _alpha() {}
"#,
)
}
2019-01-08 22:33:36 +03:00
#[test]
2019-02-04 22:09:56 +01:00
fn completes_extern_prelude() {
check(
r#"
2020-10-02 16:13:48 +02:00
//- /lib.rs crate:main deps:other_crate
2021-01-06 20:15:48 +00:00
use $0;
2020-10-02 16:13:48 +02:00
//- /other_crate/lib.rs crate:other_crate
// nothing here
"#,
expect![[r#"
md other_crate
"#]],
);
2019-02-04 22:09:56 +01:00
}
#[test]
2019-01-08 22:33:36 +03:00
fn completes_module_items_in_nested_modules() {
check(
r#"
struct Foo;
mod m {
struct Bar;
2021-01-06 20:15:48 +00:00
fn quux() { $0 }
}
"#,
expect![[r#"
fn quux() fn()
st Bar
"#]],
);
2019-01-08 22:33:36 +03:00
}
#[test]
fn completes_return_type() {
check(
r#"
struct Foo;
2021-01-06 20:15:48 +00:00
fn x() -> $0
"#,
expect![[r#"
st Foo
fn x() fn()
"#]],
);
2019-01-08 22:33:36 +03:00
}
#[test]
fn dont_show_both_completions_for_shadowing() {
check(
r#"
fn foo() {
let bar = 92;
{
let bar = 62;
2021-01-06 20:15:48 +00:00
drop($0)
}
}
"#,
// FIXME: should be only one bar here
expect![[r#"
2021-01-20 18:46:14 +01:00
lc bar i32
lc bar i32
fn foo() fn()
"#]],
);
2019-01-08 22:33:36 +03:00
}
#[test]
fn completes_self_in_methods() {
check(
2021-01-06 20:15:48 +00:00
r#"impl S { fn foo(&self) { $0 } }"#,
expect![[r#"
2021-01-20 18:46:14 +01:00
lc self &{unknown}
sp Self
"#]],
);
2019-01-08 22:33:36 +03:00
}
2019-02-13 20:53:42 +01:00
#[test]
fn completes_prelude() {
check(
r#"
2020-10-02 16:13:48 +02:00
//- /main.rs crate:main deps:std
2021-01-06 20:15:48 +00:00
fn foo() { let x: $0 }
2020-10-02 16:13:48 +02:00
//- /std/lib.rs crate:std
#[prelude_import]
use prelude::*;
mod prelude { struct Option; }
"#,
expect![[r#"
fn foo() fn()
md std
st Option
"#]],
);
2019-02-13 20:53:42 +01:00
}
2019-09-10 13:32:47 +08:00
2021-01-14 14:33:02 +03:00
#[test]
fn completes_prelude_macros() {
check(
r#"
//- /main.rs crate:main deps:std
fn f() {$0}
//- /std/lib.rs crate:std
#[prelude_import]
pub use prelude::*;
#[macro_use]
mod prelude {
pub use crate::concat;
}
mod macros {
#[rustc_builtin_macro]
#[macro_export]
macro_rules! concat { }
}
"#,
expect![[r##"
fn f() fn()
ma concat!() #[macro_export] macro_rules! concat
2021-01-14 14:33:02 +03:00
md std
"##]],
);
}
#[test]
fn completes_std_prelude_if_core_is_defined() {
check(
r#"
2020-10-02 16:13:48 +02:00
//- /main.rs crate:main deps:core,std
2021-01-06 20:15:48 +00:00
fn foo() { let x: $0 }
2020-10-02 16:13:48 +02:00
//- /core/lib.rs crate:core
#[prelude_import]
use prelude::*;
mod prelude { struct Option; }
2020-10-02 16:13:48 +02:00
//- /std/lib.rs crate:std deps:core
#[prelude_import]
use prelude::*;
mod prelude { struct String; }
"#,
expect![[r#"
fn foo() fn()
md std
md core
st String
"#]],
);
}
2019-09-10 13:32:47 +08:00
#[test]
fn completes_macros_as_value() {
check(
r#"
macro_rules! foo { () => {} }
2019-09-10 13:32:47 +08:00
#[macro_use]
mod m1 {
macro_rules! bar { () => {} }
}
2019-09-10 13:32:47 +08:00
mod m2 {
macro_rules! nope { () => {} }
2019-09-10 13:32:47 +08:00
#[macro_export]
macro_rules! baz { () => {} }
}
2019-09-10 13:32:47 +08:00
2021-01-06 20:15:48 +00:00
fn main() { let v = $0 }
"#,
expect![[r##"
md m1
ma baz!() #[macro_export] macro_rules! baz
fn main() fn()
md m2
ma bar!() macro_rules! bar
ma foo!() macro_rules! foo
"##]],
2019-09-10 13:32:47 +08:00
);
}
#[test]
fn completes_both_macro_and_value() {
check(
r#"
macro_rules! foo { () => {} }
2021-01-06 20:15:48 +00:00
fn foo() { $0 }
"#,
expect![[r#"
fn foo() fn()
ma foo!() macro_rules! foo
"#]],
2019-09-10 13:32:47 +08:00
);
}
#[test]
fn completes_macros_as_type() {
check(
r#"
macro_rules! foo { () => {} }
2021-01-06 20:15:48 +00:00
fn main() { let x: $0 }
"#,
expect![[r#"
fn main() fn()
ma foo!() macro_rules! foo
"#]],
2019-09-10 13:32:47 +08:00
);
}
#[test]
fn completes_macros_as_stmt() {
check(
r#"
macro_rules! foo { () => {} }
2021-01-06 20:15:48 +00:00
fn main() { $0 }
"#,
expect![[r#"
fn main() fn()
ma foo!() macro_rules! foo
"#]],
2019-09-10 13:32:47 +08:00
);
}
#[test]
fn completes_local_item() {
check(
r#"
fn main() {
2021-01-06 20:15:48 +00:00
return f$0;
fn frobnicate() {}
}
"#,
expect![[r#"
fn frobnicate() fn()
fn main() fn()
"#]],
);
}
2020-03-07 15:27:03 +01:00
#[test]
fn completes_in_simple_macro_1() {
check(
r#"
macro_rules! m { ($e:expr) => { $e } }
fn quux(x: i32) {
let y = 92;
2021-01-06 20:15:48 +00:00
m!($0);
}
"#,
expect![[r#"
2021-01-20 18:46:14 +01:00
lc y i32
lc x i32
fn quux() fn(i32)
ma m!() macro_rules! m
"#]],
2020-03-07 15:27:03 +01:00
);
}
#[test]
fn completes_in_simple_macro_2() {
check(
r"
macro_rules! m { ($e:expr) => { $e } }
fn quux(x: i32) {
let y = 92;
2021-01-06 20:15:48 +00:00
m!(x$0);
}
",
expect![[r#"
2021-01-20 18:46:14 +01:00
lc y i32
lc x i32
fn quux() fn(i32)
ma m!() macro_rules! m
"#]],
2020-03-15 11:26:54 +01:00
);
}
#[test]
fn completes_in_simple_macro_without_closing_parens() {
check(
r#"
macro_rules! m { ($e:expr) => { $e } }
fn quux(x: i32) {
let y = 92;
2021-01-06 20:15:48 +00:00
m!(x$0
}
"#,
expect![[r#"
2021-01-20 18:46:14 +01:00
lc y i32
lc x i32
fn quux() fn(i32)
ma m!() macro_rules! m
"#]],
2020-03-07 15:27:03 +01:00
);
}
#[test]
fn completes_unresolved_uses() {
check(
r#"
use spam::Quux;
2021-01-06 20:15:48 +00:00
fn main() { $0 }
"#,
expect![[r#"
fn main() fn()
?? Quux
"#]],
);
}
#[test]
fn completes_enum_variant_basic_expr() {
check(
r#"
enum Foo { Bar, Baz, Quux }
2021-01-06 20:15:48 +00:00
fn main() { let foo: Foo = Q$0 }
"#,
expect![[r#"
ev Foo::Bar ()
ev Foo::Baz ()
ev Foo::Quux ()
en Foo
fn main() fn()
"#]],
)
}
#[test]
fn completes_enum_variant_from_module() {
check(
r#"
mod m { pub enum E { V } }
2021-01-06 20:15:48 +00:00
fn f() -> m::E { V$0 }
"#,
expect![[r#"
ev m::E::V ()
md m
fn f() fn() -> E
"#]],
)
}
2020-05-04 16:48:50 +02:00
#[test]
fn dont_complete_attr() {
check(
r#"
struct Foo;
2021-01-06 20:15:48 +00:00
#[$0]
fn f() {}
"#,
expect![[""]],
2020-05-04 16:48:50 +02:00
)
}
#[test]
fn completes_target_type_or_trait_in_impl_block() {
check(
r#"
trait MyTrait {}
struct MyStruct {}
2021-01-06 20:15:48 +00:00
impl My$0
"#,
expect![[r#"
2021-01-20 18:46:14 +01:00
sp Self
tt MyTrait
st MyStruct
"#]],
)
}
#[test]
2021-05-27 20:53:38 +02:00
fn completes_in_assoc_item_list() {
check(
r#"
macro_rules! foo {}
2021-05-27 20:53:38 +02:00
mod bar {}
2021-05-27 20:53:38 +02:00
struct MyStruct {}
impl MyStruct {
$0
}
"#,
expect![[r#"
2021-05-27 20:53:38 +02:00
md bar
ma foo! macro_rules! foo
"#]],
)
}
2021-05-27 21:12:50 +02:00
// FIXME: The completions here currently come from `macro_in_item_position`, but they shouldn't
#[test]
fn completes_in_item_list() {
check(
r#"
struct MyStruct {}
macro_rules! foo {}
mod bar {}
$0
"#,
expect![[r#"
md bar
ma foo!() macro_rules! foo
"#]],
)
}
2019-01-08 22:33:36 +03:00
}