diff --git a/crates/ide_completion/src/completions/lifetime.rs b/crates/ide_completion/src/completions/lifetime.rs index 233bf51ec0..283dc021d6 100644 --- a/crates/ide_completion/src/completions/lifetime.rs +++ b/crates/ide_completion/src/completions/lifetime.rs @@ -10,23 +10,27 @@ use hir::ScopeDef; use syntax::ast; -use crate::{completions::Completions, context::CompletionContext}; +use crate::{ + completions::Completions, + context::{CompletionContext, LifetimeContext}, +}; /// Completes lifetimes. pub(crate) fn complete_lifetime(acc: &mut Completions, ctx: &CompletionContext) { - if !ctx.lifetime_allowed { - return; - } + let lp = match &ctx.lifetime_ctx { + Some(LifetimeContext::Lifetime) => None, + Some(LifetimeContext::LifetimeParam(param)) => param.as_ref(), + _ => return, + }; let lp_string; - let param_lifetime = - match (&ctx.name_syntax, ctx.lifetime_param_syntax.as_ref().and_then(|lp| lp.lifetime())) { - (Some(ast::NameLike::Lifetime(lt)), Some(lp)) if lp == lt.clone() => return, - (Some(_), Some(lp)) => { - lp_string = lp.to_string(); - Some(&*lp_string) - } - _ => None, - }; + let param_lifetime = match (&ctx.name_syntax, lp.and_then(|lp| lp.lifetime())) { + (Some(ast::NameLike::Lifetime(lt)), Some(lp)) if lp == lt.clone() => return, + (Some(_), Some(lp)) => { + lp_string = lp.to_string(); + Some(&*lp_string) + } + _ => None, + }; ctx.scope.process_all_names(&mut |name, res| { if let ScopeDef::GenericParam(hir::GenericParam::LifetimeParam(_)) = res { @@ -42,7 +46,7 @@ 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 { + if !matches!(ctx.lifetime_ctx, Some(LifetimeContext::LabelRef)) { return; } ctx.scope.process_all_names(&mut |name, res| { diff --git a/crates/ide_completion/src/context.rs b/crates/ide_completion/src/context.rs index b75277f628..25da46f1d7 100644 --- a/crates/ide_completion/src/context.rs +++ b/crates/ide_completion/src/context.rs @@ -60,6 +60,14 @@ pub(super) struct PatternContext { pub(super) is_param: Option, } +#[derive(Debug)] +pub(super) enum LifetimeContext { + LifetimeParam(Option), + Lifetime, + LabelRef, + LabelDef, +} + #[derive(Copy, Clone, Debug, PartialEq, Eq)] pub(crate) enum CallKind { Pat, @@ -96,16 +104,12 @@ pub(crate) struct CompletionContext<'a> { pub(super) impl_def: Option, pub(super) name_syntax: Option, - // potentially set if we are completing a lifetime - pub(super) lifetime_param_syntax: Option, - pub(super) lifetime_allowed: bool, - pub(super) is_label_ref: bool, - pub(super) completion_location: Option, pub(super) prev_sibling: Option, pub(super) attribute_under_caret: Option, pub(super) previous_token: Option, + pub(super) lifetime_ctx: Option, pub(super) pattern_ctx: Option, pub(super) path_context: Option, pub(super) locals: Vec<(String, Local)>, @@ -161,9 +165,7 @@ impl<'a> CompletionContext<'a> { function_def: None, impl_def: None, name_syntax: None, - lifetime_param_syntax: None, - lifetime_allowed: false, - is_label_ref: false, + lifetime_ctx: None, pattern_ctx: None, completion_location: None, prev_sibling: None, @@ -294,8 +296,14 @@ impl<'a> CompletionContext<'a> { self.previous_token.as_ref().map_or(false, |tok| tok.kind() == kind) } - pub(crate) fn expects_assoc_item(&self) -> bool { - matches!(self.completion_location, Some(ImmediateLocation::Trait | ImmediateLocation::Impl)) + pub(crate) fn dot_receiver(&self) -> Option<&ast::Expr> { + match &self.completion_location { + Some( + ImmediateLocation::MethodCall { receiver, .. } + | ImmediateLocation::FieldAccess { receiver, .. }, + ) => receiver.as_ref(), + _ => None, + } } pub(crate) fn has_dot_receiver(&self) -> bool { @@ -306,14 +314,8 @@ impl<'a> CompletionContext<'a> { ) } - pub(crate) fn dot_receiver(&self) -> Option<&ast::Expr> { - match &self.completion_location { - Some( - ImmediateLocation::MethodCall { receiver, .. } - | ImmediateLocation::FieldAccess { receiver, .. }, - ) => receiver.as_ref(), - _ => None, - } + pub(crate) fn expects_assoc_item(&self) -> bool { + matches!(self.completion_location, Some(ImmediateLocation::Trait | ImmediateLocation::Impl)) } pub(crate) fn expects_non_trait_assoc_item(&self) -> bool { @@ -676,19 +678,15 @@ impl<'a> CompletionContext<'a> { return; } - match_ast! { + self.lifetime_ctx = Some(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, + ast::LifetimeParam(_it) => LifetimeContext::LifetimeParam(self.sema.find_node_at_offset_with_macros(original_file, offset)), + ast::BreakExpr(_it) => LifetimeContext::LabelRef, + ast::ContinueExpr(_it) => LifetimeContext::LabelRef, + ast::Label(_it) => LifetimeContext::LabelDef, + _ => LifetimeContext::Lifetime, } - } + }); } }