1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
|
use crate::{
Cancelable,
completion::{CompletionItem, CompletionItemKind, Completions, CompletionKind, CompletionContext},
};
pub(super) fn complete_path(acc: &mut Completions, ctx: &CompletionContext) -> Cancelable<()> {
let (path, module) = match (&ctx.path_prefix, &ctx.module) {
(Some(path), Some(module)) => (path.clone(), module),
_ => return Ok(()),
};
let def_id = match module.resolve_path(ctx.db, &path)?.take_types() {
Some(it) => it,
None => return Ok(()),
};
match def_id.resolve(ctx.db)? {
hir::Def::Module(module) => {
let module_scope = module.scope(ctx.db)?;
module_scope.entries().for_each(|(name, res)| {
CompletionItem::new(CompletionKind::Reference, name.to_string())
.from_resolution(ctx, res)
.add_to(acc)
});
}
hir::Def::Enum(e) => e
.variants(ctx.db)?
.into_iter()
.for_each(|(name, _variant)| {
CompletionItem::new(CompletionKind::Reference, name.to_string())
.kind(CompletionItemKind::EnumVariant)
.add_to(acc)
}),
_ => return Ok(()),
};
Ok(())
}
#[cfg(test)]
mod tests {
use crate::completion::{CompletionKind, check_completion};
fn check_reference_completion(code: &str, expected_completions: &str) {
check_completion(code, expected_completions, CompletionKind::Reference);
}
#[test]
fn completes_use_item_starting_with_self() {
check_reference_completion(
r"
use self::m::<|>;
mod m {
struct Bar;
}
",
"Bar",
);
}
#[test]
fn completes_use_item_starting_with_crate() {
check_reference_completion(
"
//- /lib.rs
mod foo;
struct Spam;
//- /foo.rs
use crate::Sp<|>
",
"Spam;foo",
);
}
#[test]
fn completes_nested_use_tree() {
check_reference_completion(
"
//- /lib.rs
mod foo;
struct Spam;
//- /foo.rs
use crate::{Sp<|>};
",
"Spam;foo",
);
}
#[test]
fn completes_deeply_nested_use_tree() {
check_reference_completion(
"
//- /lib.rs
mod foo;
pub mod bar {
pub mod baz {
pub struct Spam;
}
}
//- /foo.rs
use crate::{bar::{baz::Sp<|>}};
",
"Spam",
);
}
#[test]
fn completes_enum_variant() {
check_reference_completion(
"
//- /lib.rs
enum E { Foo, Bar(i32) }
fn foo() { let _ = E::<|> }
",
"Foo;Bar",
);
}
}
|