about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMax Heller <max.a.heller@gmail.com>2023-07-29 11:39:59 -0400
committerMax Heller <max.a.heller@gmail.com>2023-07-29 11:39:59 -0400
commit4bb7702833f9c172694579adb53c830d5ba9ca2d (patch)
tree3dad41d8c38c2cde496194e4c2f9cdb73308a417
parentbc2b70d678f0a99484b9353cf2fdb6a0e25a3db5 (diff)
downloadrust-4bb7702833f9c172694579adb53c830d5ba9ca2d.tar.gz
rust-4bb7702833f9c172694579adb53c830d5ba9ca2d.zip
`check_edit` test
-rw-r--r--crates/ide-completion/src/tests.rs28
-rw-r--r--crates/ide-completion/src/tests/special.rs25
2 files changed, 49 insertions, 4 deletions
diff --git a/crates/ide-completion/src/tests.rs b/crates/ide-completion/src/tests.rs
index 2464e8d5f81..63c7f789d3b 100644
--- a/crates/ide-completion/src/tests.rs
+++ b/crates/ide-completion/src/tests.rs
@@ -23,6 +23,8 @@ mod type_pos;
 mod use_tree;
 mod visibility;
 
+use std::ops::ControlFlow;
+
 use expect_test::Expect;
 use hir::PrefixKind;
 use ide_db::{
@@ -185,11 +187,29 @@ pub(crate) fn check_edit_with_config(
     let (db, position) = position(ra_fixture_before);
     let completions: Vec<CompletionItem> =
         crate::completions(&db, &config, position, None).unwrap();
-    let (completion,) = completions
+    let matching = completions
         .iter()
-        .filter(|it| it.lookup() == what)
-        .collect_tuple()
-        .unwrap_or_else(|| panic!("can't find {what:?} completion in {completions:#?}"));
+        // Match IDE behavior by considering completions as matching if `what` is a subsequence
+        // of the completion's lookup text.
+        .filter(|it| {
+            let mut lookup = it.lookup().chars();
+            what.chars().all(|c| lookup.contains(&c))
+        })
+        // Select the first exact match if one exists, or the first subsequence match if not
+        .try_fold(None, |first_match, completion| {
+            let exact_match = completion.lookup() == what;
+            if exact_match {
+                ControlFlow::Break(completion)
+            } else {
+                ControlFlow::Continue(first_match.or(Some(completion)))
+            }
+        });
+    let completion = match matching {
+        ControlFlow::Continue(first_match) => first_match
+            .unwrap_or_else(|| panic!("can't find {what:?} completion in {completions:#?}")),
+        ControlFlow::Break(exact_match) => exact_match,
+    };
+
     let mut actual = db.file_text(position.file_id).to_string();
 
     let mut combined_edit = completion.text_edit.clone();
diff --git a/crates/ide-completion/src/tests/special.rs b/crates/ide-completion/src/tests/special.rs
index 3824720839e..a50184de533 100644
--- a/crates/ide-completion/src/tests/special.rs
+++ b/crates/ide-completion/src/tests/special.rs
@@ -1280,3 +1280,28 @@ fn here_we_go() {
         "#]],
     );
 }
+
+#[test]
+fn completion_filtering_excludes_non_identifier_aliases() {
+    // Catch panic instead of using `#[should_panic]` as style check bans
+    // `#[should_panic]`. Making `check_edit` return a result would require
+    // a lot of test changes.
+    std::panic::catch_unwind(|| {
+        check_edit(
+            "Partial>",
+            r#"
+#[doc(alias = ">")]
+trait PartialOrd {}
+
+struct Foo<T: Partial$0
+"#,
+            r#"
+#[doc(alias = ">")]
+trait PartialOrd {}
+
+struct Foo<T: PartialOrd
+"#,
+        )
+    })
+    .unwrap_err();
+}