[ty] Move server tests as integration tests (#19522)

## Summary

Reference:
https://github.com/astral-sh/ruff/pull/19391#discussion_r2222780892
This commit is contained in:
Dhruv Manilawala 2025-07-24 21:40:17 +05:30 committed by GitHub
parent 1d2181623c
commit f9091ea8bb
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
15 changed files with 172 additions and 128 deletions

1
Cargo.lock generated
View file

@ -4344,6 +4344,7 @@ dependencies = [
"ty_ide", "ty_ide",
"ty_project", "ty_project",
"ty_python_semantic", "ty_python_semantic",
"ty_server",
"ty_vendored", "ty_vendored",
] ]

View file

@ -38,11 +38,16 @@ tracing = { workspace = true }
tracing-subscriber = { workspace = true, features = ["chrono"] } tracing-subscriber = { workspace = true, features = ["chrono"] }
[dev-dependencies] [dev-dependencies]
ty_server = { workspace = true, features = ["testing"] }
dunce = { workspace = true } dunce = { workspace = true }
insta = { workspace = true, features = ["filters", "json"] } insta = { workspace = true, features = ["filters", "json"] }
regex = { workspace = true } regex = { workspace = true }
tempfile = { workspace = true } tempfile = { workspace = true }
[features]
testing = []
[target.'cfg(target_vendor = "apple")'.dependencies] [target.'cfg(target_vendor = "apple")'.dependencies]
libc = { workspace = true } libc = { workspace = true }

View file

@ -4,7 +4,9 @@ use anyhow::Context;
use lsp_server::Connection; use lsp_server::Connection;
use ruff_db::system::{OsSystem, SystemPathBuf}; use ruff_db::system::{OsSystem, SystemPathBuf};
use crate::server::Server; pub use crate::logging::{LogLevel, init_logging};
pub use crate::server::Server;
pub use crate::session::ClientOptions;
pub use document::{NotebookDocument, PositionEncoding, TextDocument}; pub use document::{NotebookDocument, PositionEncoding, TextDocument};
pub(crate) use session::{DocumentQuery, Session}; pub(crate) use session::{DocumentQuery, Session};
@ -14,9 +16,6 @@ mod server;
mod session; mod session;
mod system; mod system;
#[cfg(test)]
pub mod test;
pub(crate) const SERVER_NAME: &str = "ty"; pub(crate) const SERVER_NAME: &str = "ty";
pub(crate) const DIAGNOSTIC_NAME: &str = "ty"; pub(crate) const DIAGNOSTIC_NAME: &str = "ty";

View file

@ -14,7 +14,7 @@ use tracing_subscriber::fmt::time::ChronoLocal;
use tracing_subscriber::fmt::writer::BoxMakeWriter; use tracing_subscriber::fmt::writer::BoxMakeWriter;
use tracing_subscriber::layer::SubscriberExt; use tracing_subscriber::layer::SubscriberExt;
pub(crate) fn init_logging(log_level: LogLevel, log_file: Option<&SystemPath>) { pub fn init_logging(log_level: LogLevel, log_file: Option<&SystemPath>) {
let log_file = log_file let log_file = log_file
.map(|path| { .map(|path| {
// this expands `logFile` so that tildes and environment variables // this expands `logFile` so that tildes and environment variables
@ -66,7 +66,7 @@ pub(crate) fn init_logging(log_level: LogLevel, log_file: Option<&SystemPath>) {
/// The default log level is `info`. /// The default log level is `info`.
#[derive(Clone, Copy, Debug, Deserialize, Default, PartialEq, Eq, PartialOrd, Ord)] #[derive(Clone, Copy, Debug, Deserialize, Default, PartialEq, Eq, PartialOrd, Ord)]
#[serde(rename_all = "lowercase")] #[serde(rename_all = "lowercase")]
pub(crate) enum LogLevel { pub enum LogLevel {
Error, Error,
Warn, Warn,
#[default] #[default]

View file

@ -26,7 +26,7 @@ pub(crate) use api::publish_settings_diagnostics;
pub(crate) use main_loop::{Action, ConnectionSender, Event, MainLoopReceiver, MainLoopSender}; pub(crate) use main_loop::{Action, ConnectionSender, Event, MainLoopReceiver, MainLoopSender};
pub(crate) type Result<T> = std::result::Result<T, api::Error>; pub(crate) type Result<T> = std::result::Result<T, api::Error>;
pub(crate) struct Server { pub struct Server {
connection: Connection, connection: Connection,
client_capabilities: ClientCapabilities, client_capabilities: ClientCapabilities,
worker_threads: NonZeroUsize, worker_threads: NonZeroUsize,
@ -36,7 +36,7 @@ pub(crate) struct Server {
} }
impl Server { impl Server {
pub(crate) fn new( pub fn new(
worker_threads: NonZeroUsize, worker_threads: NonZeroUsize,
connection: Connection, connection: Connection,
native_system: Arc<dyn System + 'static + Send + Sync + RefUnwindSafe>, native_system: Arc<dyn System + 'static + Send + Sync + RefUnwindSafe>,
@ -161,7 +161,7 @@ impl Server {
}) })
} }
pub(crate) fn run(mut self) -> crate::Result<()> { pub fn run(mut self) -> crate::Result<()> {
let client = Client::new( let client = Client::new(
self.main_loop_sender.clone(), self.main_loop_sender.clone(),
self.connection.sender.clone(), self.connection.sender.clone(),
@ -302,89 +302,3 @@ impl Drop for ServerPanicHookHandler {
} }
} }
} }
#[cfg(test)]
mod tests {
use anyhow::Result;
use lsp_types::notification::PublishDiagnostics;
use ruff_db::system::SystemPath;
use crate::session::ClientOptions;
use crate::test::TestServerBuilder;
#[test]
fn initialization() -> Result<()> {
let server = TestServerBuilder::new()?
.build()?
.wait_until_workspaces_are_initialized()?;
let initialization_result = server.initialization_result().unwrap();
insta::assert_json_snapshot!("initialization", initialization_result);
Ok(())
}
#[test]
fn initialization_with_workspace() -> Result<()> {
let workspace_root = SystemPath::new("foo");
let server = TestServerBuilder::new()?
.with_workspace(workspace_root, ClientOptions::default())?
.build()?
.wait_until_workspaces_are_initialized()?;
let initialization_result = server.initialization_result().unwrap();
insta::assert_json_snapshot!("initialization_with_workspace", initialization_result);
Ok(())
}
#[test]
fn publish_diagnostics_on_did_open() -> Result<()> {
let workspace_root = SystemPath::new("src");
let foo = SystemPath::new("src/foo.py");
let foo_content = "\
def foo() -> str:
return 42
";
let mut server = TestServerBuilder::new()?
.with_workspace(workspace_root, ClientOptions::default())?
.with_file(foo, foo_content)?
.enable_pull_diagnostics(false)
.build()?
.wait_until_workspaces_are_initialized()?;
server.open_text_document(foo, &foo_content, 1);
let diagnostics = server.await_notification::<PublishDiagnostics>()?;
insta::assert_debug_snapshot!(diagnostics);
Ok(())
}
#[test]
fn pull_diagnostics_on_did_open() -> Result<()> {
let workspace_root = SystemPath::new("src");
let foo = SystemPath::new("src/foo.py");
let foo_content = "\
def foo() -> str:
return 42
";
let mut server = TestServerBuilder::new()?
.with_workspace(workspace_root, ClientOptions::default())?
.with_file(foo, foo_content)?
.enable_pull_diagnostics(true)
.build()?
.wait_until_workspaces_are_initialized()?;
server.open_text_document(foo, &foo_content, 1);
let diagnostics = server.document_diagnostic_request(foo)?;
insta::assert_debug_snapshot!(diagnostics);
Ok(())
}
}

View file

@ -21,7 +21,8 @@ use ty_project::{ChangeResult, Db as _, ProjectDatabase, ProjectMetadata};
pub(crate) use self::capabilities::ResolvedClientCapabilities; pub(crate) use self::capabilities::ResolvedClientCapabilities;
pub(crate) use self::index::DocumentQuery; pub(crate) use self::index::DocumentQuery;
pub(crate) use self::options::{AllOptions, ClientOptions, DiagnosticMode}; pub use self::options::ClientOptions;
pub(crate) use self::options::{AllOptions, DiagnosticMode};
pub(crate) use self::settings::ClientSettings; pub(crate) use self::settings::ClientSettings;
use crate::document::{DocumentKey, DocumentVersion, NotebookDocument}; use crate::document::{DocumentKey, DocumentVersion, NotebookDocument};
use crate::server::publish_settings_diagnostics; use crate::server::publish_settings_diagnostics;

View file

@ -49,9 +49,10 @@ struct WorkspaceOptions {
/// This is a direct representation of the settings schema sent by the client. /// This is a direct representation of the settings schema sent by the client.
#[derive(Clone, Debug, Deserialize, Default)] #[derive(Clone, Debug, Deserialize, Default)]
#[cfg_attr(test, derive(serde::Serialize, PartialEq, Eq))] #[cfg_attr(test, derive(PartialEq, Eq))]
#[cfg_attr(feature = "testing", derive(serde::Serialize))]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub(crate) struct ClientOptions { pub struct ClientOptions {
/// Settings under the `python.*` namespace in VS Code that are useful for the ty language /// Settings under the `python.*` namespace in VS Code that are useful for the ty language
/// server. /// server.
python: Option<Python>, python: Option<Python>,
@ -63,7 +64,8 @@ pub(crate) struct ClientOptions {
/// Diagnostic mode for the language server. /// Diagnostic mode for the language server.
#[derive(Clone, Copy, Debug, Default, Deserialize)] #[derive(Clone, Copy, Debug, Default, Deserialize)]
#[cfg_attr(test, derive(serde::Serialize, PartialEq, Eq))] #[cfg_attr(test, derive(PartialEq, Eq))]
#[cfg_attr(feature = "testing", derive(serde::Serialize))]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub(crate) enum DiagnosticMode { pub(crate) enum DiagnosticMode {
/// Check only currently open files. /// Check only currently open files.
@ -147,21 +149,24 @@ impl ClientOptions {
// all settings and not just the ones in "python.*". // all settings and not just the ones in "python.*".
#[derive(Clone, Debug, Deserialize, Default)] #[derive(Clone, Debug, Deserialize, Default)]
#[cfg_attr(test, derive(serde::Serialize, PartialEq, Eq))] #[cfg_attr(test, derive(PartialEq, Eq))]
#[cfg_attr(feature = "testing", derive(serde::Serialize))]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
struct Python { struct Python {
ty: Option<Ty>, ty: Option<Ty>,
} }
#[derive(Clone, Debug, Deserialize, Default)] #[derive(Clone, Debug, Deserialize, Default)]
#[cfg_attr(test, derive(serde::Serialize, PartialEq, Eq))] #[cfg_attr(test, derive(PartialEq, Eq))]
#[cfg_attr(feature = "testing", derive(serde::Serialize))]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
struct PythonExtension { struct PythonExtension {
active_environment: Option<ActiveEnvironment>, active_environment: Option<ActiveEnvironment>,
} }
#[derive(Clone, Debug, Deserialize)] #[derive(Clone, Debug, Deserialize)]
#[cfg_attr(test, derive(serde::Serialize, PartialEq, Eq))] #[cfg_attr(test, derive(PartialEq, Eq))]
#[cfg_attr(feature = "testing", derive(serde::Serialize))]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub(crate) struct ActiveEnvironment { pub(crate) struct ActiveEnvironment {
pub(crate) executable: PythonExecutable, pub(crate) executable: PythonExecutable,
@ -170,7 +175,8 @@ pub(crate) struct ActiveEnvironment {
} }
#[derive(Clone, Debug, Deserialize)] #[derive(Clone, Debug, Deserialize)]
#[cfg_attr(test, derive(serde::Serialize, PartialEq, Eq))] #[cfg_attr(test, derive(PartialEq, Eq))]
#[cfg_attr(feature = "testing", derive(serde::Serialize))]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub(crate) struct EnvironmentVersion { pub(crate) struct EnvironmentVersion {
pub(crate) major: i64, pub(crate) major: i64,
@ -182,7 +188,8 @@ pub(crate) struct EnvironmentVersion {
} }
#[derive(Clone, Debug, Deserialize)] #[derive(Clone, Debug, Deserialize)]
#[cfg_attr(test, derive(serde::Serialize, PartialEq, Eq))] #[cfg_attr(test, derive(PartialEq, Eq))]
#[cfg_attr(feature = "testing", derive(serde::Serialize))]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub(crate) struct PythonEnvironment { pub(crate) struct PythonEnvironment {
pub(crate) folder_uri: Url, pub(crate) folder_uri: Url,
@ -194,7 +201,8 @@ pub(crate) struct PythonEnvironment {
} }
#[derive(Clone, Debug, Deserialize)] #[derive(Clone, Debug, Deserialize)]
#[cfg_attr(test, derive(serde::Serialize, PartialEq, Eq))] #[cfg_attr(test, derive(PartialEq, Eq))]
#[cfg_attr(feature = "testing", derive(serde::Serialize))]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub(crate) struct PythonExecutable { pub(crate) struct PythonExecutable {
#[allow(dead_code)] #[allow(dead_code)]
@ -203,7 +211,8 @@ pub(crate) struct PythonExecutable {
} }
#[derive(Clone, Debug, Deserialize, Default)] #[derive(Clone, Debug, Deserialize, Default)]
#[cfg_attr(test, derive(serde::Serialize, PartialEq, Eq))] #[cfg_attr(test, derive(PartialEq, Eq))]
#[cfg_attr(feature = "testing", derive(serde::Serialize))]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
struct Ty { struct Ty {
disable_language_services: Option<bool>, disable_language_services: Option<bool>,

View file

@ -0,0 +1,33 @@
use anyhow::Result;
use ruff_db::system::SystemPath;
use ty_server::ClientOptions;
use crate::TestServerBuilder;
#[test]
fn empty_workspace_folders() -> Result<()> {
let server = TestServerBuilder::new()?
.build()?
.wait_until_workspaces_are_initialized()?;
let initialization_result = server.initialization_result().unwrap();
insta::assert_json_snapshot!("initialization", initialization_result);
Ok(())
}
#[test]
fn single_workspace_folder() -> Result<()> {
let workspace_root = SystemPath::new("foo");
let server = TestServerBuilder::new()?
.with_workspace(workspace_root, ClientOptions::default())?
.build()?
.wait_until_workspaces_are_initialized()?;
let initialization_result = server.initialization_result().unwrap();
insta::assert_json_snapshot!("initialization_with_workspace", initialization_result);
Ok(())
}

View file

@ -1,9 +1,35 @@
//! Testing server for the ty language server. //! Testing server for the ty language server.
//! //!
//! This module provides mock server infrastructure for testing LSP functionality using //! This module provides mock server infrastructure for testing LSP functionality using a
//! temporary directories on the real filesystem. //! temporary directory on the real filesystem.
//! //!
//! The design is inspired by the Starlark LSP test server but adapted for ty server architecture. //! The design is inspired by the Starlark LSP test server but adapted for ty server architecture.
//!
//! To get started, use the [`TestServerBuilder`] to configure the server with workspace folders,
//! enable or disable specific client capabilities, and add test files. Then, use the [`build`]
//! method to create the [`TestServer`]. This will start the server and perform the initialization
//! handshake. It might be useful to call [`wait_until_workspaces_are_initialized`] to ensure that
//! the server side initialization is complete before sending any requests.
//!
//! Once the setup is done, you can use the server to [`send_request`] and [`send_notification`] to
//! send messages to the server and [`await_response`], [`await_request`], and
//! [`await_notification`] to wait for responses, requests, and notifications from the server.
//!
//! The [`Drop`] implementation of the [`TestServer`] ensures that the server is shut down
//! gracefully using the LSP protocol. It also asserts that all messages sent by the server
//! have been handled by the test client before the server is dropped.
//!
//! [`build`]: TestServerBuilder::build
//! [`wait_until_workspaces_are_initialized`]: TestServer::wait_until_workspaces_are_initialized
//! [`send_request`]: TestServer::send_request
//! [`send_notification`]: TestServer::send_notification
//! [`await_response`]: TestServer::await_response
//! [`await_request`]: TestServer::await_request
//! [`await_notification`]: TestServer::await_notification
mod initialize;
mod publish_diagnostics;
mod pull_diagnostics;
use std::collections::hash_map::Entry; use std::collections::hash_map::Entry;
use std::collections::{HashMap, VecDeque}; use std::collections::{HashMap, VecDeque};
@ -39,9 +65,7 @@ use rustc_hash::FxHashMap;
use serde::de::DeserializeOwned; use serde::de::DeserializeOwned;
use tempfile::TempDir; use tempfile::TempDir;
use crate::logging::{LogLevel, init_logging}; use ty_server::{ClientOptions, LogLevel, Server, init_logging};
use crate::server::Server;
use crate::session::ClientOptions;
/// Number of times to retry receiving a message before giving up /// Number of times to retry receiving a message before giving up
const RETRY_COUNT: usize = 5; const RETRY_COUNT: usize = 5;
@ -86,10 +110,6 @@ impl TestServerError {
/// A test server for the ty language server that provides helpers for sending requests, /// A test server for the ty language server that provides helpers for sending requests,
/// correlating responses, and handling notifications. /// correlating responses, and handling notifications.
///
/// The [`Drop`] implementation ensures that the server is shut down gracefully using the described
/// protocol in the LSP specification. It also ensures that all messages sent by the server have
/// been handled by the test client before the server is dropped.
pub(crate) struct TestServer { pub(crate) struct TestServer {
/// The thread that's actually running the server. /// The thread that's actually running the server.
/// ///
@ -103,10 +123,10 @@ pub(crate) struct TestServer {
/// the connection to be cleaned up properly. /// the connection to be cleaned up properly.
client_connection: Option<Connection>, client_connection: Option<Connection>,
/// Test directory that holds all test files. /// Test context that provides the project root directory that holds all test files.
/// ///
/// This directory is automatically cleaned up when the [`TestServer`] is dropped. /// This directory is automatically cleaned up when the [`TestServer`] is dropped.
test_dir: TestContext, test_context: TestContext,
/// Incrementing counter to automatically generate request IDs /// Incrementing counter to automatically generate request IDs
request_counter: i32, request_counter: i32,
@ -175,7 +195,7 @@ impl TestServer {
Self { Self {
server_thread: Some(server_thread), server_thread: Some(server_thread),
client_connection: Some(client_connection), client_connection: Some(client_connection),
test_dir, test_context: test_dir,
request_counter: 0, request_counter: 0,
responses: FxHashMap::default(), responses: FxHashMap::default(),
notifications: VecDeque::new(), notifications: VecDeque::new(),
@ -297,9 +317,9 @@ impl TestServer {
/// Send a request to the server and return the request ID. /// Send a request to the server and return the request ID.
/// ///
/// The caller can use this ID to later retrieve the response using [`get_response`]. /// The caller can use this ID to later retrieve the response using [`await_response`].
/// ///
/// [`get_response`]: TestServer::get_response /// [`await_response`]: TestServer::await_response
pub(crate) fn send_request<R>(&mut self, params: R::Params) -> RequestId pub(crate) fn send_request<R>(&mut self, params: R::Params) -> RequestId
where where
R: Request, R: Request,
@ -505,7 +525,7 @@ impl TestServer {
/// Use the [`get_request`] method to wait for the server to send this request. /// Use the [`get_request`] method to wait for the server to send this request.
/// ///
/// [`get_request`]: TestServer::get_request /// [`get_request`]: TestServer::get_request
pub(crate) fn handle_workspace_configuration_request( fn handle_workspace_configuration_request(
&mut self, &mut self,
request_id: RequestId, request_id: RequestId,
params: &ConfigurationParams, params: &ConfigurationParams,
@ -548,7 +568,7 @@ impl TestServer {
} }
fn file_uri(&self, path: impl AsRef<SystemPath>) -> Url { fn file_uri(&self, path: impl AsRef<SystemPath>) -> Url {
Url::from_file_path(self.test_dir.root().join(path.as_ref()).as_std_path()) Url::from_file_path(self.test_context.root().join(path.as_ref()).as_std_path())
.expect("Path must be a valid URL") .expect("Path must be a valid URL")
} }
@ -628,7 +648,7 @@ impl TestServer {
impl fmt::Debug for TestServer { impl fmt::Debug for TestServer {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("TestServer") f.debug_struct("TestServer")
.field("temp_dir", &self.test_dir.root()) .field("temp_dir", &self.test_context.root())
.field("request_counter", &self.request_counter) .field("request_counter", &self.request_counter)
.field("responses", &self.responses) .field("responses", &self.responses)
.field("notifications", &self.notifications) .field("notifications", &self.notifications)
@ -750,6 +770,7 @@ impl TestServerBuilder {
} }
/// Enable or disable pull diagnostics capability /// Enable or disable pull diagnostics capability
#[must_use]
pub(crate) fn enable_pull_diagnostics(mut self, enabled: bool) -> Self { pub(crate) fn enable_pull_diagnostics(mut self, enabled: bool) -> Self {
self.client_capabilities self.client_capabilities
.text_document .text_document
@ -763,6 +784,7 @@ impl TestServerBuilder {
} }
/// Enable or disable file watching capability /// Enable or disable file watching capability
#[must_use]
#[expect(dead_code)] #[expect(dead_code)]
pub(crate) fn enable_did_change_watched_files(mut self, enabled: bool) -> Self { pub(crate) fn enable_did_change_watched_files(mut self, enabled: bool) -> Self {
self.client_capabilities self.client_capabilities
@ -777,6 +799,7 @@ impl TestServerBuilder {
} }
/// Set custom client capabilities (overrides any previously set capabilities) /// Set custom client capabilities (overrides any previously set capabilities)
#[must_use]
#[expect(dead_code)] #[expect(dead_code)]
pub(crate) fn with_client_capabilities(mut self, capabilities: ClientCapabilities) -> Self { pub(crate) fn with_client_capabilities(mut self, capabilities: ClientCapabilities) -> Self {
self.client_capabilities = capabilities; self.client_capabilities = capabilities;
@ -798,7 +821,7 @@ impl TestServerBuilder {
Ok(self) Ok(self)
} }
/// Write multiple files to the temporary directory /// Write multiple files to the test directory
#[expect(dead_code)] #[expect(dead_code)]
pub(crate) fn with_files<P, C, I>(mut self, files: I) -> Result<Self> pub(crate) fn with_files<P, C, I>(mut self, files: I) -> Result<Self>
where where

View file

@ -0,0 +1,30 @@
use anyhow::Result;
use lsp_types::notification::PublishDiagnostics;
use ruff_db::system::SystemPath;
use ty_server::ClientOptions;
use crate::TestServerBuilder;
#[test]
fn on_did_open() -> Result<()> {
let workspace_root = SystemPath::new("src");
let foo = SystemPath::new("src/foo.py");
let foo_content = "\
def foo() -> str:
return 42
";
let mut server = TestServerBuilder::new()?
.with_workspace(workspace_root, ClientOptions::default())?
.with_file(foo, foo_content)?
.enable_pull_diagnostics(false)
.build()?
.wait_until_workspaces_are_initialized()?;
server.open_text_document(foo, &foo_content, 1);
let diagnostics = server.await_notification::<PublishDiagnostics>()?;
insta::assert_debug_snapshot!(diagnostics);
Ok(())
}

View file

@ -0,0 +1,29 @@
use anyhow::Result;
use ruff_db::system::SystemPath;
use ty_server::ClientOptions;
use crate::TestServerBuilder;
#[test]
fn on_did_open() -> Result<()> {
let workspace_root = SystemPath::new("src");
let foo = SystemPath::new("src/foo.py");
let foo_content = "\
def foo() -> str:
return 42
";
let mut server = TestServerBuilder::new()?
.with_workspace(workspace_root, ClientOptions::default())?
.with_file(foo, foo_content)?
.enable_pull_diagnostics(true)
.build()?
.wait_until_workspaces_are_initialized()?;
server.open_text_document(foo, &foo_content, 1);
let diagnostics = server.document_diagnostic_request(foo)?;
insta::assert_debug_snapshot!(diagnostics);
Ok(())
}

View file

@ -1,5 +1,5 @@
--- ---
source: crates/ty_server/src/server.rs source: crates/ty_server/tests/e2e/initialize.rs
expression: initialization_result expression: initialization_result
--- ---
{ {

View file

@ -1,5 +1,5 @@
--- ---
source: crates/ty_server/src/server.rs source: crates/ty_server/tests/e2e/initialize.rs
expression: initialization_result expression: initialization_result
--- ---
{ {

View file

@ -1,5 +1,5 @@
--- ---
source: crates/ty_server/src/server.rs source: crates/ty_server/tests/e2e/publish_diagnostics.rs
expression: diagnostics expression: diagnostics
--- ---
PublishDiagnosticsParams { PublishDiagnosticsParams {

View file

@ -1,5 +1,5 @@
--- ---
source: crates/ty_server/src/server.rs source: crates/ty_server/tests/e2e/pull_diagnostics.rs
expression: diagnostics expression: diagnostics
--- ---
Report( Report(