Skip to content

Commit 9f9cc72

Browse files
committed
Complete crate, super and self in non-usetree paths
1 parent 2b6770c commit 9f9cc72

File tree

10 files changed

+126
-57
lines changed

10 files changed

+126
-57
lines changed

crates/ide_completion/src/completions.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,12 @@ impl Completions {
7474
items.into_iter().for_each(|item| self.add(item.into()))
7575
}
7676

77+
pub(crate) fn add_keyword(&mut self, ctx: &CompletionContext, keyword: &'static str) {
78+
let mut item = CompletionItem::new(CompletionKind::Keyword, ctx.source_range(), keyword);
79+
item.kind(CompletionItemKind::Keyword);
80+
item.add_to(self);
81+
}
82+
7783
pub(crate) fn add_resolution(
7884
&mut self,
7985
ctx: &CompletionContext,

crates/ide_completion/src/completions/keyword.rs

Lines changed: 21 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,44 +1,12 @@
11
//! Completes keywords.
22
3-
use std::iter;
4-
53
use syntax::{SyntaxKind, T};
64

75
use crate::{
86
context::PathCompletionContext, patterns::ImmediateLocation, CompletionContext, CompletionItem,
97
CompletionItemKind, CompletionKind, Completions,
108
};
119

12-
pub(crate) fn complete_use_tree_keyword(acc: &mut Completions, ctx: &CompletionContext) {
13-
// complete keyword "crate" in use stmt
14-
let source_range = ctx.source_range();
15-
let kw_completion = move |text: &str| {
16-
let mut item = CompletionItem::new(CompletionKind::Keyword, source_range, text);
17-
item.kind(CompletionItemKind::Keyword).insert_text(text);
18-
item
19-
};
20-
21-
if ctx.in_use_tree() {
22-
match &ctx.path_context {
23-
Some(PathCompletionContext { qualifier: Some(qual), use_tree_parent, .. }) => {
24-
if iter::successors(Some(qual.clone()), |p| p.qualifier())
25-
.all(|p| p.segment().and_then(|s| s.super_token()).is_some())
26-
{
27-
kw_completion("super::").add_to(acc);
28-
}
29-
if *use_tree_parent {
30-
kw_completion("self").add_to(acc);
31-
}
32-
}
33-
_ => {
34-
kw_completion("crate::").add_to(acc);
35-
kw_completion("self::").add_to(acc);
36-
kw_completion("super::").add_to(acc);
37-
}
38-
};
39-
}
40-
}
41-
4210
pub(crate) fn complete_expr_keyword(acc: &mut Completions, ctx: &CompletionContext) {
4311
if ctx.token.kind() == SyntaxKind::COMMENT {
4412
cov_mark::hit!(no_keyword_completion_in_comments);
@@ -243,6 +211,9 @@ mod tests {
243211
kw for
244212
kw let
245213
kw return
214+
kw self
215+
kw super
216+
kw crate
246217
"#]],
247218
);
248219
}
@@ -271,6 +242,9 @@ mod tests {
271242
kw for
272243
kw let
273244
kw return
245+
kw self
246+
kw super
247+
kw crate
274248
"#]],
275249
);
276250
}
@@ -301,6 +275,9 @@ mod tests {
301275
kw else
302276
kw else if
303277
kw return
278+
kw self
279+
kw super
280+
kw crate
304281
"#]],
305282
);
306283
check_edit(
@@ -330,6 +307,9 @@ fn quux() -> i32 {
330307
kw if let
331308
kw for
332309
kw return
310+
kw self
311+
kw super
312+
kw crate
333313
"#]],
334314
);
335315
}
@@ -360,6 +340,9 @@ fn quux() -> i32 {
360340
kw continue
361341
kw break
362342
kw return
343+
kw self
344+
kw super
345+
kw crate
363346
"#]],
364347
);
365348
}
@@ -448,6 +431,9 @@ fn foo() {
448431
kw if let
449432
kw for
450433
kw return
434+
kw self
435+
kw super
436+
kw crate
451437
"#]],
452438
)
453439
}
@@ -493,6 +479,9 @@ fn foo() {
493479
kw if let
494480
kw for
495481
kw return
482+
kw self
483+
kw super
484+
kw crate
496485
"#]],
497486
);
498487
}

crates/ide_completion/src/completions/qualified_path.rs

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,22 @@
11
//! Completion of paths, i.e. `some::prefix::$0`.
22
3+
use std::iter;
4+
35
use hir::HasVisibility;
46
use rustc_hash::FxHashSet;
5-
use syntax::AstNode;
7+
use syntax::{ast, AstNode};
68

7-
use crate::{CompletionContext, Completions};
9+
use crate::{context::PathCompletionContext, CompletionContext, Completions};
810

911
pub(crate) fn complete_qualified_path(acc: &mut Completions, ctx: &CompletionContext) {
1012
if ctx.is_path_disallowed() {
1113
return;
1214
}
13-
let path = match ctx.path_qual() {
14-
Some(path) => path,
15-
None => return,
15+
let (path, use_tree_parent) = match &ctx.path_context {
16+
Some(PathCompletionContext { qualifier: Some(qualifier), use_tree_parent, .. }) => {
17+
(qualifier, *use_tree_parent)
18+
}
19+
_ => return,
1620
};
1721

1822
let resolution = match ctx.sema.resolve_path(path) {
@@ -39,6 +43,23 @@ pub(crate) fn complete_qualified_path(acc: &mut Completions, ctx: &CompletionCon
3943
return;
4044
}
4145

46+
if ctx.in_use_tree() {
47+
if iter::successors(Some(path.clone()), |p| p.qualifier())
48+
.all(|p| p.segment().and_then(|s| s.super_token()).is_some())
49+
{
50+
acc.add_keyword(ctx, "super::");
51+
}
52+
// only show `self` in a new use-tree when the qualifier doesn't end in self
53+
if use_tree_parent
54+
&& !matches!(
55+
path.segment().and_then(|it| it.kind()),
56+
Some(ast::PathSegmentKind::SelfKw)
57+
)
58+
{
59+
acc.add_keyword(ctx, "self");
60+
}
61+
}
62+
4263
// Add associated types on type parameters and `Self`.
4364
resolution.assoc_type_shorthand_candidates(ctx.db, |_, alias| {
4465
acc.add_type_alias(ctx, alias);

crates/ide_completion/src/completions/unqualified_path.rs

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,21 @@ pub(crate) fn complete_unqualified_path(acc: &mut Completions, ctx: &CompletionC
1010
return;
1111
}
1212

13+
if ctx.in_use_tree() {
14+
// only show modules in a fresh UseTree
15+
cov_mark::hit!(only_completes_modules_in_import);
16+
ctx.scope.process_all_names(&mut |name, res| {
17+
if let ScopeDef::ModuleDef(hir::ModuleDef::Module(_)) = res {
18+
acc.add_resolution(ctx, name, &res);
19+
}
20+
});
21+
22+
std::array::IntoIter::new(["self::", "super::", "crate::"])
23+
.for_each(|kw| acc.add_keyword(ctx, kw));
24+
return;
25+
}
26+
std::array::IntoIter::new(["self", "super", "crate"]).for_each(|kw| acc.add_keyword(ctx, kw));
27+
1328
if ctx.expects_item() || ctx.expects_assoc_item() {
1429
// only show macros in {Assoc}ItemList
1530
ctx.scope.process_all_names(&mut |name, res| {
@@ -25,17 +40,6 @@ pub(crate) fn complete_unqualified_path(acc: &mut Completions, ctx: &CompletionC
2540
return;
2641
}
2742

28-
if ctx.in_use_tree() {
29-
// only show modules in a fresh UseTree
30-
cov_mark::hit!(only_completes_modules_in_import);
31-
ctx.scope.process_all_names(&mut |name, res| {
32-
if let ScopeDef::ModuleDef(hir::ModuleDef::Module(_)) = res {
33-
acc.add_resolution(ctx, name, &res);
34-
}
35-
});
36-
return;
37-
}
38-
3943
if matches!(&ctx.completion_location, Some(ImmediateLocation::TypeBound)) {
4044
ctx.scope.process_all_names(&mut |name, res| {
4145
let add_resolution = match res {

crates/ide_completion/src/lib.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,6 @@ pub fn completions(
150150
completions::attribute::complete_attribute(&mut acc, &ctx);
151151
completions::fn_param::complete_fn_param(&mut acc, &ctx);
152152
completions::keyword::complete_expr_keyword(&mut acc, &ctx);
153-
completions::keyword::complete_use_tree_keyword(&mut acc, &ctx);
154153
completions::snippet::complete_expr_snippet(&mut acc, &ctx);
155154
completions::snippet::complete_item_snippet(&mut acc, &ctx);
156155
completions::qualified_path::complete_qualified_path(&mut acc, &ctx);

crates/ide_completion/src/tests/item_list.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,9 @@ fn in_mod_item_list() {
3030
sn tmod (Test module)
3131
sn tfn (Test function)
3232
sn macro_rules
33+
kw self
34+
kw super
35+
kw crate
3336
ma makro!(…) #[macro_export] macro_rules! makro
3437
"##]],
3538
)
@@ -58,6 +61,9 @@ fn in_source_file_item_list() {
5861
sn tmod (Test module)
5962
sn tfn (Test function)
6063
sn macro_rules
64+
kw self
65+
kw super
66+
kw crate
6167
ma makro!(…) #[macro_export] macro_rules! makro
6268
md module
6369
ma makro!(…) #[macro_export] macro_rules! makro
@@ -174,6 +180,9 @@ fn in_impl_assoc_item_list() {
174180
kw fn
175181
kw const
176182
kw type
183+
kw self
184+
kw super
185+
kw crate
177186
ma makro!(…) #[macro_export] macro_rules! makro
178187
md module
179188
ma makro!(…) #[macro_export] macro_rules! makro
@@ -205,6 +214,9 @@ fn in_trait_assoc_item_list() {
205214
kw fn
206215
kw const
207216
kw type
217+
kw self
218+
kw super
219+
kw crate
208220
md module
209221
ma makro!(…) #[macro_export] macro_rules! makro
210222
ma makro!(…) #[macro_export] macro_rules! makro

crates/ide_completion/src/tests/items.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@ fn target_type_or_trait_in_impl_block() {
1818
impl Tra$0
1919
"#,
2020
expect![[r##"
21+
kw self
22+
kw super
23+
kw crate
2124
tt Trait
2225
en Enum
2326
st Record
@@ -38,6 +41,9 @@ fn target_type_in_trait_impl_block() {
3841
impl Trait for Str$0
3942
"#,
4043
expect![[r##"
44+
kw self
45+
kw super
46+
kw crate
4147
tt Trait
4248
en Enum
4349
st Record

crates/ide_completion/src/tests/predicate.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@ fn predicate_start() {
1616
struct Foo<'lt, T, const C: usize> where $0 {}
1717
"#,
1818
expect![[r##"
19+
kw self
20+
kw super
21+
kw crate
1922
tt Trait
2023
en Enum
2124
st Record
@@ -38,6 +41,9 @@ fn bound_for_type_pred() {
3841
struct Foo<'lt, T, const C: usize> where T: $0 {}
3942
"#,
4043
expect![[r##"
44+
kw self
45+
kw super
46+
kw crate
4147
tt Trait
4248
md module
4349
ma makro!(…) #[macro_export] macro_rules! makro
@@ -54,6 +60,9 @@ fn bound_for_lifetime_pred() {
5460
struct Foo<'lt, T, const C: usize> where 'lt: $0 {}
5561
"#,
5662
expect![[r##"
63+
kw self
64+
kw super
65+
kw crate
5766
tt Trait
5867
md module
5968
ma makro!(…) #[macro_export] macro_rules! makro
@@ -69,6 +78,9 @@ fn bound_for_for_pred() {
6978
struct Foo<'lt, T, const C: usize> where for<'a> T: $0 {}
7079
"#,
7180
expect![[r##"
81+
kw self
82+
kw super
83+
kw crate
7284
tt Trait
7385
md module
7486
ma makro!(…) #[macro_export] macro_rules! makro
@@ -84,6 +96,9 @@ fn param_list_for_for_pred() {
8496
struct Foo<'lt, T, const C: usize> where for<'a> $0 {}
8597
"#,
8698
expect![[r##"
99+
kw self
100+
kw super
101+
kw crate
87102
tt Trait
88103
en Enum
89104
st Record
@@ -107,6 +122,9 @@ impl Record {
107122
}
108123
"#,
109124
expect![[r##"
125+
kw self
126+
kw super
127+
kw crate
110128
sp Self
111129
tt Trait
112130
en Enum

crates/ide_completion/src/tests/type_pos.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,9 @@ struct Foo<'lt, T, const C: usize> {
3030
}
3131
"#,
3232
expect![[r#"
33+
kw self
34+
kw super
35+
kw crate
3336
sp Self
3437
tp T
3538
tt Trait
@@ -54,6 +57,9 @@ struct Foo<'lt, T, const C: usize>(f$0);
5457
expect![[r#"
5558
kw pub(crate)
5659
kw pub
60+
kw self
61+
kw super
62+
kw crate
5763
sp Self
5864
tp T
5965
tt Trait
@@ -76,6 +82,9 @@ fn fn_return_type() {
7682
fn x<'lt, T, const C: usize>() -> $0
7783
"#,
7884
expect![[r#"
85+
kw self
86+
kw super
87+
kw crate
7988
tp T
8089
tt Trait
8190
en Enum
@@ -99,6 +108,9 @@ fn foo<'lt, T, const C: usize>() {
99108
}
100109
"#,
101110
expect![[r#"
111+
kw self
112+
kw super
113+
kw crate
102114
tp T
103115
tt Trait
104116
en Enum
@@ -140,6 +152,9 @@ trait Trait2 {
140152
fn foo<'lt, T: Trait2<$0>, const CONST_PARAM: usize>(_: T) {}
141153
"#,
142154
expect![[r#"
155+
kw self
156+
kw super
157+
kw crate
143158
ta Foo = (as Trait2) type Foo;
144159
tp T
145160
cp CONST_PARAM

0 commit comments

Comments
 (0)