1 //! Completes lifetimes and labels.
3 //! These completions work a bit differently in that they are only shown when what the user types
4 //! has a `'` preceding it, as our fake syntax tree is invalid otherwise (due to us not inserting
5 //! a lifetime but an ident for obvious reasons).
6 //! Due to this all the tests for lifetimes and labels live in this module for the time being as
7 //! there is no value in lifting these out into the outline module test since they will either not
8 //! show up for normal completions, or they won't show completions other than lifetimes depending
9 //! on the fixture input.
14 completions::Completions,
15 context::{CompletionContext, LifetimeContext},
18 /// Completes lifetimes.
19 pub(crate) fn complete_lifetime(acc: &mut Completions, ctx: &CompletionContext) {
20 let lp = match &ctx.lifetime_ctx {
21 Some(LifetimeContext::Lifetime) => None,
22 Some(LifetimeContext::LifetimeParam(param)) => param.as_ref(),
26 let param_lifetime = match (&ctx.name_syntax, lp.and_then(|lp| lp.lifetime())) {
27 (Some(ast::NameLike::Lifetime(lt)), Some(lp)) if lp == lt.clone() => return,
28 (Some(_), Some(lp)) => {
29 lp_string = lp.to_string();
35 ctx.scope.process_all_names(&mut |name, res| {
36 if let ScopeDef::GenericParam(hir::GenericParam::LifetimeParam(_)) = res {
37 if param_lifetime != Some(&*name.to_string()) {
38 acc.add_resolution(ctx, name, &res);
42 if param_lifetime.is_none() {
43 acc.add_static_lifetime(ctx);
48 pub(crate) fn complete_label(acc: &mut Completions, ctx: &CompletionContext) {
49 if !matches!(ctx.lifetime_ctx, Some(LifetimeContext::LabelRef)) {
52 ctx.scope.process_all_names(&mut |name, res| {
53 if let ScopeDef::Label(_) = res {
54 acc.add_resolution(ctx, name, &res);
61 use expect_test::{expect, Expect};
63 use crate::tests::{check_edit, completion_list};
65 fn check(ra_fixture: &str, expect: Expect) {
66 let actual = completion_list(ra_fixture);
67 expect.assert_eq(&actual);
71 fn check_lifetime_edit() {
75 fn func<'lifetime>(foo: &'li$0) {}
78 fn func<'lifetime>(foo: &'lifetime) {}
81 cov_mark::check!(completes_if_lifetime_without_idents);
85 fn func<'lifetime>(foo: &'$0) {}
88 fn func<'lifetime>(foo: &'lifetime) {}
94 fn complete_lifetime_in_ref() {
97 fn foo<'lifetime>(foo: &'a$0 usize) {}
107 fn complete_lifetime_in_ref_missing_ty() {
110 fn foo<'lifetime>(foo: &'a$0) {}
119 fn complete_lifetime_in_self_ref() {
124 fn foo<'func>(&'a$0 self) {}
136 fn complete_lifetime_in_arg_list() {
140 fn foo<'lifetime>(_: Foo<'a$0>) {}
150 fn complete_lifetime_in_where_pred() {
153 fn foo2<'lifetime, T>() where 'a$0 {}
163 fn complete_lifetime_in_ty_bound() {
166 fn foo2<'lifetime, T>() where T: 'a$0 {}
175 fn foo2<'lifetime, T>() where T: Trait<'a$0> {}
185 fn dont_complete_lifetime_in_assoc_ty_bound() {
188 fn foo2<'lifetime, T>() where T: Trait<Item = 'a$0> {}
195 fn complete_lifetime_in_param_list() {
204 fn foo<'footime, 'lifetime: 'a$0>() {}
213 fn check_label_edit() {
234 fn complete_label_in_loop() {
262 fn complete_label_in_block_nested() {
281 fn complete_label_in_loop_with_value() {
297 fn complete_label_in_while_cond() {
301 'outer: while { 'inner: loop { break '$0 } } {}
312 fn complete_label_in_for_iterable() {
316 'outer: for _ in [{ 'inner: loop { break '$0 } }] {}