Repository: astral-sh/ruff
File: crates/ty_ide/src/completion.rs (Rust)

Code before:
        predicate: Option<Box<dyn Fn(&Completion) -> bool>>,
    }

    impl CompletionTestBuilder {
        /// Returns completions based on this configuration.
        fn build(&self) -> CompletionTest<'_> {
            let original = completion(
                &self.cursor_test.db,
                &self.settings,
                self.cursor_test.cursor.file,
                self.cursor_test.cursor.offset,
            );
            let filtered = original
                .iter()
                .filter(|c| !self.skip_builtins || !c.builtin)
                .filter(|c| {
                    self.predicate
                        .as_ref()
                        .map(|predicate| predicate(c))
                        .unwrap_or(true)
                })
                .cloned()
                .collect();
            CompletionTest {
                db: self.db(),
                original,
                filtered,
                type_signatures: self.type_signatures,
                module_names: self.module_names,
            }
        }

        /// Returns the underlying test DB.
        fn db(&self) -> &ty_project::TestDb {
            &self.cursor_test.db
        }

        /// When enabled, symbols that aren't in scope but available
        /// in the environment will be included.
        ///
        /// Not enabled by default.
        fn auto_import(mut self) -> CompletionTestBuilder {
            self.settings.auto_import = true;
            self
        }

        /// When set, builtins from completions are skipped. This is
        /// useful in tests to reduce noise for scope based completions.
        ///
        /// Not enabled by default.
        fn skip_builtins(mut self) -> CompletionTestBuilder {

Review comment (suggestion):
A version of this test with _three_ preceding dots doesn't pass. The reason is that `from ...foo` doesn't parse as `[<FROM>, <DOT>, <DOT>, <DOT>, <NAME("foo")>]`, it parses as `[<FROM>, <ELLIPSIS>, <NAME("foo")>]`.

You want to make this change:

```diff
diff --git a/crates/ty_ide/src/completion.rs b/crates/ty_ide/src/completion.rs
index d6896f3804..adf107d7c4 100644
--- a/crates/ty_ide/src/completion.rs
+++ b/crates/ty_ide/src/completion.rs
@@ -919,7 +919,8 @@ fn from_import_statement_keyword_completions<'db>(tokens: &[Token]) -> Option<Co
     // Skip over '('.' | '...')*'
     let dots_count = tokens_after_from
         .iter()
-        .take_while(|t| t.kind() == TokenKind::Dot)
+        .map(Token::kind)
+        .take_while(|t| matches!(t, TokenKind::Dot | TokenKind::Ellipsis))
         .count();
 
     let tokens_after_dots = &tokens_after_from[dots_count..];
@@ -4391,6 +4392,23 @@ type <CURSOR>
         assert!(completions.len() == 1);
     }
 
+    #[test]
+    fn from_import_nested_very_dotted_name_relative_import_suggests_import() {
+        let builder = CursorTest::builder()
+            // N.B. the `...` tokenizes as `TokenKind::Ellipsis`
+            .source("src/main.py", "from ...foo i<CURSOR>")
+            .source("foo.py", "")
+            .completion_test_builder();
+
+        let completions_test = builder.build();
+
+        completions_test.contains("import");
+
+        let completions = completions_test.completions();
+
+        assert!(completions.len() == 1);
+    }
+
     /// A way to create a simple single-file (named `main.py`) completion test
     /// builder.
     ///
```

Code after:
    }

    #[test]
    fn from_import_only_dot_incomplete() {
        let builder = CursorTest::builder()
            .source(
                "main.py",
                "
                import_zqzqzq = 1
                from .imp<CURSOR>
                ",
            )
            .completion_test_builder();
        assert_snapshot!(builder.build().snapshot(), @"import");
    }

    #[test]
    fn from_import_incomplete() {
        let builder = completion_test_builder(
            "from collections.abc i

             ZQZQZQ = 1
             ZQ<CURSOR>",
        );
        assert_snapshot!(builder.build().snapshot(), @"ZQZQZQ");
    }

    /// A way to create a simple single-file (named `main.py`) completion test
    /// builder.
    ///
    /// Use cases that require multiple files with a `<CURSOR>` marker
    /// in a file other than `main.py` can use `CursorTest::builder()`
    /// and then `CursorTestBuilder::completion_test_builder()`.
    fn completion_test_builder(source: &str) -> CompletionTestBuilder {
        CursorTest::builder()
            .source("main.py", source)
            .completion_test_builder()
    }

    /// A builder for executing a completion test.
    ///
    /// This mostly owns the responsibility for generating snapshots
    /// of completions from a cursor position in source code. Most of
    /// the options involve some kind of filtering or adjustment to
    /// apply to the snapshots, depending on what one wants to test.
    struct CompletionTestBuilder {
        cursor_test: CursorTest,
        settings: CompletionSettings,
        skip_builtins: bool,
        type_signatures: bool,
        module_names: bool,