]> git.lizzy.rs Git - rust.git/blobdiff - crates/ide_completion/src/completions/lifetime.rs
internal: Refactor lifetime completion context fields
[rust.git] / crates / ide_completion / src / completions / lifetime.rs
index 628c1fb9b6cb97dabd9dd8926fe43a591cc191cc..283dc021d6ecb0c71339ded36c8ce09d35c5546f 100644 (file)
@@ -1,26 +1,41 @@
 //! Completes lifetimes and labels.
+//!
+//! These completions work a bit differently in that they are only shown when what the user types
+//! has a `'` preceding it, as our fake syntax tree is invalid otherwise (due to us not inserting
+//! a lifetime but an ident for obvious reasons).
+//! Due to this all the tests for lifetimes and labels live in this module for the time being as
+//! there is no value in lifting these out into the outline module test since they will either not
+//! show up for normal completions, or they won't show completions other than lifetimes depending
+//! on the fixture input.
 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 param_lifetime = match (
-        &ctx.lifetime_syntax,
-        ctx.lifetime_param_syntax.as_ref().and_then(|lp| lp.lifetime()),
-    ) {
-        (Some(lt), Some(lp)) if lp == lt.clone() => return,
-        (Some(_), Some(lp)) => Some(lp.to_string()),
+    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, 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 {
-            if param_lifetime != Some(name.to_string()) {
-                acc.add_resolution(ctx, name.to_string(), &res);
+            if param_lifetime != Some(&*name.to_string()) {
+                acc.add_resolution(ctx, name, &res);
             }
         }
     });
@@ -31,12 +46,12 @@ 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| {
         if let ScopeDef::Label(_) = res {
-            acc.add_resolution(ctx, name.to_string(), &res);
+            acc.add_resolution(ctx, name, &res);
         }
     });
 }
@@ -45,18 +60,11 @@ pub(crate) fn complete_label(acc: &mut Completions, ctx: &CompletionContext) {
 mod tests {
     use expect_test::{expect, Expect};
 
-    use crate::{
-        test_utils::{check_edit, completion_list_with_config, TEST_CONFIG},
-        CompletionConfig, CompletionKind,
-    };
+    use crate::tests::{check_edit, completion_list};
 
     fn check(ra_fixture: &str, expect: Expect) {
-        check_with_config(TEST_CONFIG, ra_fixture, expect);
-    }
-
-    fn check_with_config(config: CompletionConfig, ra_fixture: &str, expect: Expect) {
-        let actual = completion_list_with_config(config, ra_fixture, CompletionKind::Reference);
-        expect.assert_eq(&actual)
+        let actual = completion_list(ra_fixture);
+        expect.assert_eq(&actual);
     }
 
     #[test]
@@ -68,6 +76,16 @@ fn func<'lifetime>(foo: &'li$0) {}
 "#,
             r#"
 fn func<'lifetime>(foo: &'lifetime) {}
+"#,
+        );
+        cov_mark::check!(completes_if_lifetime_without_idents);
+        check_edit(
+            "'lifetime",
+            r#"
+fn func<'lifetime>(foo: &'$0) {}
+"#,
+            r#"
+fn func<'lifetime>(foo: &'lifetime) {}
 "#,
         );
     }
@@ -191,6 +209,27 @@ fn foo<'footime, 'lifetime: 'a$0>() {}
         );
     }
 
+    #[test]
+    fn check_label_edit() {
+        check_edit(
+            "'label",
+            r#"
+fn foo() {
+    'label: loop {
+        break '$0
+    }
+}
+"#,
+            r#"
+fn foo() {
+    'label: loop {
+        break 'label
+    }
+}
+"#,
+        );
+    }
+
     #[test]
     fn complete_label_in_loop() {
         check(