Skip to content

Commit 62a4677

Browse files
committed
Add label completion
1 parent cbd3257 commit 62a4677

File tree

4 files changed

+100
-7
lines changed

4 files changed

+100
-7
lines changed

crates/ide_completion/src/completions/lifetime.rs

Lines changed: 76 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
//! Completes lifetimes.
1+
//! Completes lifetimes and labels.
22
use hir::ScopeDef;
33

44
use crate::{completions::Completions, context::CompletionContext};
@@ -29,6 +29,18 @@ pub(crate) fn complete_lifetime(acc: &mut Completions, ctx: &CompletionContext)
2929
}
3030
}
3131

32+
/// Completes labels.
33+
pub(crate) fn complete_label(acc: &mut Completions, ctx: &CompletionContext) {
34+
if !ctx.is_label_ref {
35+
return;
36+
}
37+
ctx.scope.process_all_names(&mut |name, res| {
38+
if let ScopeDef::Label(_) = res {
39+
acc.add_resolution(ctx, name.to_string(), &res);
40+
}
41+
});
42+
}
43+
3244
#[cfg(test)]
3345
mod tests {
3446
use expect_test::{expect, Expect};
@@ -178,4 +190,67 @@ fn foo<'footime, 'lifetime: 'a$0>() {}
178190
"#]],
179191
);
180192
}
193+
194+
#[test]
195+
fn complete_label_in_loop() {
196+
check(
197+
r#"
198+
fn foo() {
199+
'foop: loop {
200+
break '$0
201+
}
202+
}
203+
"#,
204+
expect![[r#"
205+
lb 'foop
206+
"#]],
207+
);
208+
check(
209+
r#"
210+
fn foo() {
211+
'foop: loop {
212+
continue '$0
213+
}
214+
}
215+
"#,
216+
expect![[r#"
217+
lb 'foop
218+
"#]],
219+
);
220+
}
221+
222+
#[test]
223+
fn complete_label_in_block_nested() {
224+
check(
225+
r#"
226+
fn foo() {
227+
'foop: {
228+
'baap: {
229+
break '$0
230+
}
231+
}
232+
}
233+
"#,
234+
expect![[r#"
235+
lb 'baap
236+
lb 'foop
237+
"#]],
238+
);
239+
}
240+
241+
#[test]
242+
fn complete_label_in_loop_with_value() {
243+
check(
244+
r#"
245+
fn foo() {
246+
'foop: loop {
247+
break '$0 i32;
248+
}
249+
}
250+
"#,
251+
expect![[r#"
252+
lb 'foop
253+
"#]],
254+
);
255+
}
181256
}

crates/ide_completion/src/context.rs

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ pub(crate) struct CompletionContext<'a> {
5353
/// FIXME: `ActiveParameter` is string-based, which is very very wrong
5454
pub(super) active_parameter: Option<ActiveParameter>,
5555
pub(super) is_param: bool,
56+
pub(super) is_label_ref: bool,
5657
/// If a name-binding or reference to a const in a pattern.
5758
/// Irrefutable patterns (like let) are excluded.
5859
pub(super) is_pat_binding_or_const: bool,
@@ -155,6 +156,7 @@ impl<'a> CompletionContext<'a> {
155156
record_field_syntax: None,
156157
impl_def: None,
157158
active_parameter: ActiveParameter::at(db, position),
159+
is_label_ref: false,
158160
is_param: false,
159161
is_pat_binding_or_const: false,
160162
is_irrefutable_pat_binding: false,
@@ -468,12 +470,26 @@ impl<'a> CompletionContext<'a> {
468470
) {
469471
self.lifetime_syntax =
470472
find_node_at_offset(original_file, lifetime.syntax().text_range().start());
471-
if lifetime.syntax().parent().map_or(false, |p| p.kind() != syntax::SyntaxKind::ERROR) {
472-
self.lifetime_allowed = true;
473-
}
474-
if let Some(_) = lifetime.syntax().parent().and_then(ast::LifetimeParam::cast) {
475-
self.lifetime_param_syntax =
476-
self.sema.find_node_at_offset_with_macros(original_file, offset);
473+
if let Some(parent) = lifetime.syntax().parent() {
474+
if parent.kind() == syntax::SyntaxKind::ERROR {
475+
return;
476+
}
477+
478+
if parent.kind() != syntax::SyntaxKind::LABEL {
479+
match_ast! {
480+
match parent {
481+
ast::LifetimeParam(_it) => {
482+
self.lifetime_allowed = true;
483+
self.lifetime_param_syntax =
484+
self.sema.find_node_at_offset_with_macros(original_file, offset);
485+
},
486+
ast::BreakExpr(_it) => self.is_label_ref = true,
487+
ast::ContinueExpr(_it) => self.is_label_ref = true,
488+
ast::Label(_it) => (),
489+
_ => self.lifetime_allowed = true,
490+
}
491+
}
492+
}
477493
}
478494
}
479495

crates/ide_completion/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,7 @@ pub fn completions(
131131
completions::mod_::complete_mod(&mut acc, &ctx);
132132
completions::flyimport::import_on_the_fly(&mut acc, &ctx);
133133
completions::lifetime::complete_lifetime(&mut acc, &ctx);
134+
completions::lifetime::complete_label(&mut acc, &ctx);
134135

135136
Some(acc)
136137
}

crates/ide_completion/src/render.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,7 @@ impl<'a> Render<'a> {
219219
hir::GenericParam::ConstParam(_) => SymbolKind::ConstParam,
220220
}),
221221
ScopeDef::Local(..) => CompletionItemKind::SymbolKind(SymbolKind::Local),
222+
ScopeDef::Label(..) => CompletionItemKind::SymbolKind(SymbolKind::Label),
222223
ScopeDef::AdtSelfType(..) | ScopeDef::ImplSelfType(..) => {
223224
CompletionItemKind::SymbolKind(SymbolKind::SelfParam)
224225
}

0 commit comments

Comments
 (0)