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

Code before:
        is_typeddict :: , is_typeddict
        _FilterConfigurationTypedDict :: from logging.config import _FilterConfigurationTypedDict

        _FormatterConfigurationTypedDict :: from logging.config import _FormatterConfigurationTypedDict
        ",
        );
    }

    // Tests that when we have `Unknown | T` that we offer
    // completions for `T`.
    #[test]
    fn dynamic_type() {
        let builder = completion_test_builder(
            r#"
my_list = ["foo"]
my_list[0].remove<CURSOR>
"#,
        );
        assert_snapshot!(
            builder.build().snapshot(),
            @r"
        removeprefix
        removesuffix
        ",
        );
    }

    /// 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.
    #[expect(clippy::struct_excessive_bools)] // free the bools!
    struct CompletionTestBuilder {
        cursor_test: CursorTest,
        settings: CompletionSettings,
        skip_builtins: bool,
        skip_keywords: bool,

Review comment (suggestion):
this test could be a bit fragile, considering that we intend to change our behaviour here in the future -- this won't be inferred as `Unknown | str` at all in the long term. I think it's a useful integration test anyway, but you could also add a direct unit test as well that will continue to directly test the change you're making here even if we change how we infer the elements of unannotated list literals:

```rs
    #[test]
    fn dynamic_type_2() {
        let builder = completion_test_builder(
            r#"
from typing import Any

def f(x: Any | str):
    x.remove<CURSOR>
"#,
        );
        assert_snapshot!(
            builder.build().snapshot(),
            @r"
        removeprefix
        removesuffix
        ",
        );
    }

Code after:
        is_typeddict :: , is_typeddict
        _FilterConfigurationTypedDict :: from logging.config import _FilterConfigurationTypedDict

        _FormatterConfigurationTypedDict :: from logging.config import _FormatterConfigurationTypedDict
        ",
        );
    }

    /// Tests that `xs = ["..."]; xs[0].<CURSOR>` gets completions
    /// appropriate for `str`.
    #[test]
    fn dynamic_type_list_no_type_annotation() {
        let builder = completion_test_builder(
            r#"
my_list = ["foo"]
my_list[0].remove<CURSOR>
"#,
        );
        assert_snapshot!(
            builder.build().snapshot(),
            @r"
        removeprefix
        removesuffix
        ",
        );
    }

    /// Tests that when we have `Any | T` that we offer
    /// completions for `T`.
    #[test]
    fn dynamic_type_with_type_annotation() {
        let builder = completion_test_builder(
            r#"
from typing import Any

def f(x: Any | str):
    x.remove<CURSOR>
"#,
        );
        assert_snapshot!(
            builder.build().snapshot(),
            @r"
        removeprefix
        removesuffix
        ",
        );
    }

    /// Tests that when we have `(U & Any) | T` that we offer
    /// completions for `T`.
    #[test]