From 1e2c81df8002574fd6b096f1703b46129be83ea9 Mon Sep 17 00:00:00 2001 From: Andrew Gallant Date: Fri, 12 Dec 2025 10:11:35 -0500 Subject: [PATCH] [ty] Add tests for how qualified auto-imports are shown Specifically, we want to test that something like `import typing` should only be shown when we are actually going to insert an import. *And* that when we insert a qualified name, then we should show it as such in the completion suggestions. --- crates/ty_server/tests/e2e/completions.rs | 211 +++++++++++++++++++++- 1 file changed, 207 insertions(+), 4 deletions(-) diff --git a/crates/ty_server/tests/e2e/completions.rs b/crates/ty_server/tests/e2e/completions.rs index 80576100b6..24efe82ea9 100644 --- a/crates/ty_server/tests/e2e/completions.rs +++ b/crates/ty_server/tests/e2e/completions.rs @@ -24,9 +24,9 @@ walktr server.open_text_document(foo, foo_content, 1); let _ = server.await_notification::(); - let hints = server.completion_request(&server.file_uri(foo), Position::new(0, 6)); + let completions = server.completion_request(&server.file_uri(foo), Position::new(0, 6)); - insta::assert_json_snapshot!(hints, @r#" + insta::assert_json_snapshot!(completions, @r#" [ { "label": "walktree (import inspect)", @@ -74,9 +74,212 @@ walktr server.open_text_document(foo, foo_content, 1); let _ = server.await_notification::(); - let hints = server.completion_request(&server.file_uri(foo), Position::new(0, 6)); + let completions = server.completion_request(&server.file_uri(foo), Position::new(0, 6)); - insta::assert_json_snapshot!(hints, @"[]"); + insta::assert_json_snapshot!(completions, @"[]"); + + Ok(()) +} + +/// Tests that auto-import completions show the fully +/// qualified form when it will insert it for you. Also, +/// that an `import` won't be shown when it won't +/// actually be inserted. +#[test] +fn auto_import_shows_qualification() -> Result<()> { + let workspace_root = SystemPath::new("src"); + let foo = SystemPath::new("src/foo.py"); + let foo_content = "\ +import typing + +TypedDi +"; + + let mut server = TestServerBuilder::new()? + .with_initialization_options(ClientOptions::default()) + .with_workspace(workspace_root, None)? + .with_file(foo, foo_content)? + .build() + .wait_until_workspaces_are_initialized(); + + server.open_text_document(foo, foo_content, 1); + let _ = server.await_notification::(); + + let completions = server.completion_request(&server.file_uri(foo), Position::new(2, 7)); + + insta::assert_json_snapshot!(completions, @r#" + [ + { + "label": "TypedDict (import typing)", + "kind": 6, + "sortText": "0", + "insertText": "typing.TypedDict" + }, + { + "label": "is_typeddict (import typing)", + "kind": 3, + "sortText": "1", + "insertText": "typing.is_typeddict" + }, + { + "label": "_FilterConfigurationTypedDict (import logging.config)", + "kind": 7, + "sortText": "2", + "insertText": "_FilterConfigurationTypedDict", + "additionalTextEdits": [ + { + "range": { + "start": { + "line": 0, + "character": 0 + }, + "end": { + "line": 0, + "character": 0 + } + }, + "newText": "from logging.config import _FilterConfigurationTypedDict\n" + } + ] + }, + { + "label": "_FormatterConfigurationTypedDict (import logging.config)", + "kind": 6, + "sortText": "3", + "insertText": "_FormatterConfigurationTypedDict", + "additionalTextEdits": [ + { + "range": { + "start": { + "line": 0, + "character": 0 + }, + "end": { + "line": 0, + "character": 0 + } + }, + "newText": "from logging.config import _FormatterConfigurationTypedDict\n" + } + ] + } + ] + "#); + + Ok(()) +} + +/// Tests that auto-import completions show the fully +/// qualified form when it will insert it for you *and* +/// will also show the import when it will be inserted. +#[test] +fn auto_import_shows_qualification_and_import() -> Result<()> { + let workspace_root = SystemPath::new("src"); + let foo = SystemPath::new("src/foo.py"); + let foo_content = "\ +TypedDi +"; + + let mut server = TestServerBuilder::new()? + .with_initialization_options(ClientOptions::default()) + .with_workspace(workspace_root, None)? + .with_file(foo, foo_content)? + .build() + .wait_until_workspaces_are_initialized(); + + server.open_text_document(foo, foo_content, 1); + let _ = server.await_notification::(); + + let completions = server.completion_request(&server.file_uri(foo), Position::new(0, 7)); + + insta::assert_json_snapshot!(completions, @r#" + [ + { + "label": "TypedDict (import typing)", + "kind": 6, + "sortText": "0", + "insertText": "TypedDict", + "additionalTextEdits": [ + { + "range": { + "start": { + "line": 0, + "character": 0 + }, + "end": { + "line": 0, + "character": 0 + } + }, + "newText": "from typing import TypedDict\n" + } + ] + }, + { + "label": "is_typeddict (import typing)", + "kind": 3, + "sortText": "1", + "insertText": "is_typeddict", + "additionalTextEdits": [ + { + "range": { + "start": { + "line": 0, + "character": 0 + }, + "end": { + "line": 0, + "character": 0 + } + }, + "newText": "from typing import is_typeddict\n" + } + ] + }, + { + "label": "_FilterConfigurationTypedDict (import logging.config)", + "kind": 7, + "sortText": "2", + "insertText": "_FilterConfigurationTypedDict", + "additionalTextEdits": [ + { + "range": { + "start": { + "line": 0, + "character": 0 + }, + "end": { + "line": 0, + "character": 0 + } + }, + "newText": "from logging.config import _FilterConfigurationTypedDict\n" + } + ] + }, + { + "label": "_FormatterConfigurationTypedDict (import logging.config)", + "kind": 6, + "sortText": "3", + "insertText": "_FormatterConfigurationTypedDict", + "additionalTextEdits": [ + { + "range": { + "start": { + "line": 0, + "character": 0 + }, + "end": { + "line": 0, + "character": 0 + } + }, + "newText": "from logging.config import _FormatterConfigurationTypedDict\n" + } + ] + } + ] + "#); Ok(()) }