Skip to content

Commit ae0c726

Browse files
committed
internal: completion: split out more PathKinds from ImmediateLocation
1 parent 49b0970 commit ae0c726

File tree

10 files changed

+206
-160
lines changed

10 files changed

+206
-160
lines changed

crates/ide_completion/src/completions/flyimport.rs

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -110,14 +110,19 @@ pub(crate) fn import_on_the_fly(acc: &mut Completions, ctx: &CompletionContext)
110110
if !ctx.config.enable_imports_on_the_fly {
111111
return None;
112112
}
113-
if ctx.in_use_tree()
113+
if matches!(ctx.path_kind(), Some(PathKind::Vis { .. } | PathKind::Use))
114114
|| ctx.is_path_disallowed()
115115
|| ctx.expects_item()
116116
|| ctx.expects_assoc_item()
117117
|| ctx.expects_variant()
118118
{
119119
return None;
120120
}
121+
// FIXME: This should be encoded in a different way
122+
if ctx.pattern_ctx.is_none() && ctx.path_context.is_none() && !ctx.has_dot_receiver() {
123+
// completion inside `ast::Name` of a item declaration
124+
return None;
125+
}
121126
let potential_import_name = {
122127
let token_kind = ctx.token.kind();
123128
if matches!(token_kind, T![.] | T![::]) {
@@ -147,14 +152,25 @@ pub(crate) fn import_on_the_fly(acc: &mut Completions, ctx: &CompletionContext)
147152
}
148153
};
149154
match (kind, import.original_item) {
155+
// Aren't handled in flyimport
156+
(PathKind::Vis { .. } | PathKind::Use, _) => false,
157+
// modules are always fair game
158+
(_, ItemInNs::Types(hir::ModuleDef::Module(_))) => true,
159+
// and so are macros(except for attributes)
160+
(
161+
PathKind::Expr | PathKind::Type | PathKind::Mac | PathKind::Pat,
162+
ItemInNs::Macros(mac),
163+
) => mac.is_fn_like(),
164+
(PathKind::Mac, _) => true,
165+
150166
(PathKind::Expr, ItemInNs::Types(_) | ItemInNs::Values(_)) => true,
151167

168+
(PathKind::Pat, ItemInNs::Types(_)) => true,
169+
(PathKind::Pat, ItemInNs::Values(def)) => matches!(def, hir::ModuleDef::Const(_)),
170+
152171
(PathKind::Type, ItemInNs::Types(_)) => true,
153172
(PathKind::Type, ItemInNs::Values(_)) => false,
154173

155-
(PathKind::Expr | PathKind::Type, ItemInNs::Macros(mac)) => mac.is_fn_like(),
156-
157-
(PathKind::Attr, ItemInNs::Types(hir::ModuleDef::Module(_))) => true,
158174
(PathKind::Attr, ItemInNs::Macros(mac)) => mac.is_attr(),
159175
(PathKind::Attr, _) => false,
160176
}

crates/ide_completion/src/completions/keyword.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,9 @@
55
use syntax::{SyntaxKind, T};
66

77
use crate::{
8-
context::PathCompletionContext, patterns::ImmediateLocation, CompletionContext, CompletionItem,
9-
CompletionItemKind, Completions,
8+
context::{PathCompletionContext, PathKind},
9+
patterns::ImmediateLocation,
10+
CompletionContext, CompletionItem, CompletionItemKind, Completions,
1011
};
1112

1213
pub(crate) fn complete_expr_keyword(acc: &mut Completions, ctx: &CompletionContext) {
@@ -33,8 +34,8 @@ pub(crate) fn complete_expr_keyword(acc: &mut Completions, ctx: &CompletionConte
3334
let has_block_expr_parent = ctx.has_block_expr_parent();
3435
let expects_item = ctx.expects_item();
3536

36-
if let Some(ImmediateLocation::Visibility(vis)) = &ctx.completion_location {
37-
if vis.in_token().is_none() {
37+
if let Some(PathKind::Vis { has_in_token }) = ctx.path_kind() {
38+
if !has_in_token {
3839
cov_mark::hit!(kw_completion_in);
3940
add_keyword("in", "in");
4041
}

crates/ide_completion/src/completions/pattern.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,17 @@
1-
//! Completes constants and paths in patterns.
1+
//! Completes constants and paths in unqualified patterns.
22
33
use crate::{
44
context::{PatternContext, PatternRefutability},
55
CompletionContext, Completions,
66
};
77

8-
/// Completes constants and paths in patterns.
8+
/// Completes constants and paths in unqualified patterns.
99
pub(crate) fn complete_pattern(acc: &mut Completions, ctx: &CompletionContext) {
1010
let refutable = match ctx.pattern_ctx {
11-
Some(PatternContext { refutability, .. }) => refutability == PatternRefutability::Refutable,
12-
None => return,
11+
Some(PatternContext { refutability, .. }) if ctx.path_context.is_none() => {
12+
refutability == PatternRefutability::Refutable
13+
}
14+
_ => return,
1315
};
1416

1517
if refutable {

crates/ide_completion/src/completions/qualified_path.rs

Lines changed: 40 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,23 @@ use rustc_hash::FxHashSet;
77
use syntax::{ast, AstNode};
88

99
use crate::{
10-
context::PathCompletionContext, patterns::ImmediateLocation, CompletionContext, Completions,
10+
context::{PathCompletionContext, PathKind},
11+
patterns::ImmediateLocation,
12+
CompletionContext, Completions,
1113
};
1214

1315
pub(crate) fn complete_qualified_path(acc: &mut Completions, ctx: &CompletionContext) {
1416
if ctx.is_path_disallowed() || ctx.has_impl_or_trait_prev_sibling() {
1517
return;
1618
}
17-
let (path, use_tree_parent) = match &ctx.path_context {
18-
Some(PathCompletionContext { qualifier: Some(qualifier), use_tree_parent, .. }) => {
19-
(qualifier, *use_tree_parent)
20-
}
19+
let (path, use_tree_parent, kind) = match ctx.path_context {
20+
// let ... else, syntax would come in really handy here right now
21+
Some(PathCompletionContext {
22+
qualifier: Some(ref qualifier),
23+
use_tree_parent,
24+
kind,
25+
..
26+
}) => (qualifier, use_tree_parent, kind),
2127
_ => return,
2228
};
2329

@@ -44,7 +50,11 @@ pub(crate) fn complete_qualified_path(acc: &mut Completions, ctx: &CompletionCon
4450
}
4551
return;
4652
}
47-
Some(ImmediateLocation::Visibility(_)) => {
53+
_ => (),
54+
}
55+
56+
match kind {
57+
Some(PathKind::Vis { .. }) => {
4858
if let hir::PathResolution::Def(hir::ModuleDef::Module(module)) = resolution {
4959
if let Some(current_module) = ctx.scope.module() {
5060
if let Some(next) = current_module
@@ -61,7 +71,7 @@ pub(crate) fn complete_qualified_path(acc: &mut Completions, ctx: &CompletionCon
6171
}
6272
return;
6373
}
64-
Some(ImmediateLocation::Attribute(_)) => {
74+
Some(PathKind::Attr) => {
6575
if let hir::PathResolution::Def(hir::ModuleDef::Module(module)) = resolution {
6676
for (name, def) in module.scope(ctx.db, context_module) {
6777
let add_resolution = match def {
@@ -76,37 +86,38 @@ pub(crate) fn complete_qualified_path(acc: &mut Completions, ctx: &CompletionCon
7686
}
7787
return;
7888
}
89+
Some(PathKind::Use) => {
90+
if iter::successors(Some(path.clone()), |p| p.qualifier())
91+
.all(|p| p.segment().and_then(|s| s.super_token()).is_some())
92+
{
93+
acc.add_keyword(ctx, "super::");
94+
}
95+
// only show `self` in a new use-tree when the qualifier doesn't end in self
96+
if use_tree_parent
97+
&& !matches!(
98+
path.segment().and_then(|it| it.kind()),
99+
Some(ast::PathSegmentKind::SelfKw)
100+
)
101+
{
102+
acc.add_keyword(ctx, "self");
103+
}
104+
}
79105
_ => (),
80106
}
81107

82-
if ctx.in_use_tree() {
83-
if iter::successors(Some(path.clone()), |p| p.qualifier())
84-
.all(|p| p.segment().and_then(|s| s.super_token()).is_some())
85-
{
86-
acc.add_keyword(ctx, "super::");
87-
}
88-
// only show `self` in a new use-tree when the qualifier doesn't end in self
89-
if use_tree_parent
90-
&& !matches!(
91-
path.segment().and_then(|it| it.kind()),
92-
Some(ast::PathSegmentKind::SelfKw)
93-
)
94-
{
95-
acc.add_keyword(ctx, "self");
96-
}
108+
if !matches!(kind, Some(PathKind::Pat)) {
109+
// Add associated types on type parameters and `Self`.
110+
resolution.assoc_type_shorthand_candidates(ctx.db, |_, alias| {
111+
acc.add_type_alias(ctx, alias);
112+
None::<()>
113+
});
97114
}
98115

99-
// Add associated types on type parameters and `Self`.
100-
resolution.assoc_type_shorthand_candidates(ctx.db, |_, alias| {
101-
acc.add_type_alias(ctx, alias);
102-
None::<()>
103-
});
104-
105116
match resolution {
106117
hir::PathResolution::Def(hir::ModuleDef::Module(module)) => {
107118
let module_scope = module.scope(ctx.db, context_module);
108119
for (name, def) in module_scope {
109-
if ctx.in_use_tree() {
120+
if let Some(PathKind::Use) = kind {
110121
if let ScopeDef::Unknown = def {
111122
if let Some(ast::NameLike::NameRef(name_ref)) = ctx.name_syntax.as_ref() {
112123
if name_ref.syntax().text() == name.to_smol_str().as_str() {

crates/ide_completion/src/completions/unqualified_path.rs

Lines changed: 29 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,23 @@
33
use hir::ScopeDef;
44
use syntax::{ast, AstNode};
55

6-
use crate::{patterns::ImmediateLocation, CompletionContext, Completions};
6+
use crate::{
7+
context::{PathCompletionContext, PathKind},
8+
patterns::ImmediateLocation,
9+
CompletionContext, Completions,
10+
};
711

812
pub(crate) fn complete_unqualified_path(acc: &mut Completions, ctx: &CompletionContext) {
913
let _p = profile::span("complete_unqualified_path");
10-
if ctx.is_path_disallowed() || !ctx.is_trivial_path() || ctx.has_impl_or_trait_prev_sibling() {
14+
if ctx.is_path_disallowed() || ctx.has_impl_or_trait_prev_sibling() {
1115
return;
1216
}
17+
let kind = match ctx.path_context {
18+
Some(PathCompletionContext { is_trivial_path: true, kind, .. }) => kind,
19+
_ => return,
20+
};
1321

14-
if ctx.in_use_tree() {
22+
if let Some(PathKind::Use) = kind {
1523
// only show modules in a fresh UseTree
1624
cov_mark::hit!(unqualified_path_only_modules_in_import);
1725
ctx.process_all_names(&mut |name, res| {
@@ -25,8 +33,25 @@ pub(crate) fn complete_unqualified_path(acc: &mut Completions, ctx: &CompletionC
2533
}
2634
["self", "super", "crate"].into_iter().for_each(|kw| acc.add_keyword(ctx, kw));
2735

36+
match kind {
37+
Some(PathKind::Vis { .. }) => return,
38+
Some(PathKind::Attr) => {
39+
ctx.process_all_names(&mut |name, res| {
40+
let add_resolution = match res {
41+
ScopeDef::MacroDef(mac) => mac.is_attr(),
42+
ScopeDef::ModuleDef(hir::ModuleDef::Module(_)) => true,
43+
_ => false,
44+
};
45+
if add_resolution {
46+
acc.add_resolution(ctx, name, &res);
47+
}
48+
});
49+
return;
50+
}
51+
_ => (),
52+
}
53+
2854
match &ctx.completion_location {
29-
Some(ImmediateLocation::Visibility(_)) => return,
3055
Some(ImmediateLocation::ItemList | ImmediateLocation::Trait | ImmediateLocation::Impl) => {
3156
// only show macros in {Assoc}ItemList
3257
ctx.process_all_names(&mut |name, res| {
@@ -56,19 +81,6 @@ pub(crate) fn complete_unqualified_path(acc: &mut Completions, ctx: &CompletionC
5681
});
5782
return;
5883
}
59-
Some(ImmediateLocation::Attribute(_)) => {
60-
ctx.process_all_names(&mut |name, res| {
61-
let add_resolution = match res {
62-
ScopeDef::MacroDef(mac) => mac.is_attr(),
63-
ScopeDef::ModuleDef(hir::ModuleDef::Module(_)) => true,
64-
_ => false,
65-
};
66-
if add_resolution {
67-
acc.add_resolution(ctx, name, &res);
68-
}
69-
});
70-
return;
71-
}
7284
_ => (),
7385
}
7486

0 commit comments

Comments
 (0)