Add label completion

This commit is contained in:
Lukas Wirth 2021-03-21 01:00:09 +01:00
parent cbd325707b
commit 62a4677dbc
4 changed files with 100 additions and 7 deletions

View File

@ -1,4 +1,4 @@
//! Completes lifetimes.
//! Completes lifetimes and labels.
use hir::ScopeDef;
use crate::{completions::Completions, context::CompletionContext};
@ -29,6 +29,18 @@ pub(crate) fn complete_lifetime(acc: &mut Completions, ctx: &CompletionContext)
}
}
/// Completes labels.
pub(crate) fn complete_label(acc: &mut Completions, ctx: &CompletionContext) {
if !ctx.is_label_ref {
return;
}
ctx.scope.process_all_names(&mut |name, res| {
if let ScopeDef::Label(_) = res {
acc.add_resolution(ctx, name.to_string(), &res);
}
});
}
#[cfg(test)]
mod tests {
use expect_test::{expect, Expect};
@ -178,4 +190,67 @@ fn foo<'footime, 'lifetime: 'a$0>() {}
"#]],
);
}
#[test]
fn complete_label_in_loop() {
check(
r#"
fn foo() {
'foop: loop {
break '$0
}
}
"#,
expect![[r#"
lb 'foop
"#]],
);
check(
r#"
fn foo() {
'foop: loop {
continue '$0
}
}
"#,
expect![[r#"
lb 'foop
"#]],
);
}
#[test]
fn complete_label_in_block_nested() {
check(
r#"
fn foo() {
'foop: {
'baap: {
break '$0
}
}
}
"#,
expect![[r#"
lb 'baap
lb 'foop
"#]],
);
}
#[test]
fn complete_label_in_loop_with_value() {
check(
r#"
fn foo() {
'foop: loop {
break '$0 i32;
}
}
"#,
expect![[r#"
lb 'foop
"#]],
);
}
}

View File

@ -53,6 +53,7 @@ pub(crate) struct CompletionContext<'a> {
/// FIXME: `ActiveParameter` is string-based, which is very very wrong
pub(super) active_parameter: Option<ActiveParameter>,
pub(super) is_param: bool,
pub(super) is_label_ref: bool,
/// If a name-binding or reference to a const in a pattern.
/// Irrefutable patterns (like let) are excluded.
pub(super) is_pat_binding_or_const: bool,
@ -155,6 +156,7 @@ impl<'a> CompletionContext<'a> {
record_field_syntax: None,
impl_def: None,
active_parameter: ActiveParameter::at(db, position),
is_label_ref: false,
is_param: false,
is_pat_binding_or_const: false,
is_irrefutable_pat_binding: false,
@ -468,12 +470,26 @@ impl<'a> CompletionContext<'a> {
) {
self.lifetime_syntax =
find_node_at_offset(original_file, lifetime.syntax().text_range().start());
if lifetime.syntax().parent().map_or(false, |p| p.kind() != syntax::SyntaxKind::ERROR) {
self.lifetime_allowed = true;
}
if let Some(_) = lifetime.syntax().parent().and_then(ast::LifetimeParam::cast) {
self.lifetime_param_syntax =
self.sema.find_node_at_offset_with_macros(original_file, offset);
if let Some(parent) = lifetime.syntax().parent() {
if parent.kind() == syntax::SyntaxKind::ERROR {
return;
}
if parent.kind() != syntax::SyntaxKind::LABEL {
match_ast! {
match parent {
ast::LifetimeParam(_it) => {
self.lifetime_allowed = true;
self.lifetime_param_syntax =
self.sema.find_node_at_offset_with_macros(original_file, offset);
},
ast::BreakExpr(_it) => self.is_label_ref = true,
ast::ContinueExpr(_it) => self.is_label_ref = true,
ast::Label(_it) => (),
_ => self.lifetime_allowed = true,
}
}
}
}
}

View File

@ -131,6 +131,7 @@ pub fn completions(
completions::mod_::complete_mod(&mut acc, &ctx);
completions::flyimport::import_on_the_fly(&mut acc, &ctx);
completions::lifetime::complete_lifetime(&mut acc, &ctx);
completions::lifetime::complete_label(&mut acc, &ctx);
Some(acc)
}

View File

@ -219,6 +219,7 @@ impl<'a> Render<'a> {
hir::GenericParam::ConstParam(_) => SymbolKind::ConstParam,
}),
ScopeDef::Local(..) => CompletionItemKind::SymbolKind(SymbolKind::Local),
ScopeDef::Label(..) => CompletionItemKind::SymbolKind(SymbolKind::Label),
ScopeDef::AdtSelfType(..) | ScopeDef::ImplSelfType(..) => {
CompletionItemKind::SymbolKind(SymbolKind::SelfParam)
}