[ty] Use concise message for LSP clients not supporting related diagnostic information (#21850)

This commit is contained in:
Micha Reiser 2025-12-09 13:18:30 +01:00 committed by GitHub
parent dc2f0a86fd
commit 11901384b4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
24 changed files with 361 additions and 471 deletions

View File

@ -36,6 +36,7 @@ bitflags::bitflags! {
const WORKSPACE_CONFIGURATION = 1 << 15; const WORKSPACE_CONFIGURATION = 1 << 15;
const RENAME_DYNAMIC_REGISTRATION = 1 << 16; const RENAME_DYNAMIC_REGISTRATION = 1 << 16;
const COMPLETION_ITEM_LABEL_DETAILS_SUPPORT = 1 << 17; const COMPLETION_ITEM_LABEL_DETAILS_SUPPORT = 1 << 17;
const DIAGNOSTIC_RELATED_INFORMATION = 1 << 18;
} }
} }
@ -163,6 +164,11 @@ impl ResolvedClientCapabilities {
self.contains(Self::DIAGNOSTIC_DYNAMIC_REGISTRATION) self.contains(Self::DIAGNOSTIC_DYNAMIC_REGISTRATION)
} }
/// Returns `true` if the client has related information support for diagnostics.
pub(crate) const fn supports_diagnostic_related_information(self) -> bool {
self.contains(Self::DIAGNOSTIC_RELATED_INFORMATION)
}
/// Returns `true` if the client supports dynamic registration for rename capabilities. /// Returns `true` if the client supports dynamic registration for rename capabilities.
pub(crate) const fn supports_rename_dynamic_registration(self) -> bool { pub(crate) const fn supports_rename_dynamic_registration(self) -> bool {
self.contains(Self::RENAME_DYNAMIC_REGISTRATION) self.contains(Self::RENAME_DYNAMIC_REGISTRATION)
@ -211,15 +217,22 @@ impl ResolvedClientCapabilities {
} }
} }
if text_document.is_some_and(|text_document| text_document.diagnostic.is_some()) { if let Some(diagnostic) =
text_document.and_then(|text_document| text_document.diagnostic.as_ref())
{
flags |= Self::PULL_DIAGNOSTICS; flags |= Self::PULL_DIAGNOSTICS;
if diagnostic.dynamic_registration == Some(true) {
flags |= Self::DIAGNOSTIC_DYNAMIC_REGISTRATION;
}
} }
if text_document if let Some(publish_diagnostics) =
.and_then(|text_document| text_document.diagnostic.as_ref()?.dynamic_registration) text_document.and_then(|text_document| text_document.publish_diagnostics.as_ref())
.unwrap_or_default()
{ {
flags |= Self::DIAGNOSTIC_DYNAMIC_REGISTRATION; if publish_diagnostics.related_information == Some(true) {
flags |= Self::DIAGNOSTIC_RELATED_INFORMATION;
}
} }
if text_document if text_document

View File

@ -16,6 +16,7 @@ use ruff_db::system::SystemPathBuf;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use ty_project::{Db as _, ProjectDatabase}; use ty_project::{Db as _, ProjectDatabase};
use crate::capabilities::ResolvedClientCapabilities;
use crate::document::{FileRangeExt, ToRangeExt}; use crate::document::{FileRangeExt, ToRangeExt};
use crate::session::DocumentHandle; use crate::session::DocumentHandle;
use crate::session::client::Client; use crate::session::client::Client;
@ -56,7 +57,11 @@ impl Diagnostics {
Self::result_id_from_hash(&self.items) Self::result_id_from_hash(&self.items)
} }
pub(super) fn to_lsp_diagnostics(&self, db: &ProjectDatabase) -> LspDiagnostics { pub(super) fn to_lsp_diagnostics(
&self,
db: &ProjectDatabase,
client_capabilities: ResolvedClientCapabilities,
) -> LspDiagnostics {
if let Some(notebook_document) = db.notebook_document(self.file_or_notebook) { if let Some(notebook_document) = db.notebook_document(self.file_or_notebook) {
let mut cell_diagnostics: FxHashMap<Url, Vec<Diagnostic>> = FxHashMap::default(); let mut cell_diagnostics: FxHashMap<Url, Vec<Diagnostic>> = FxHashMap::default();
@ -67,7 +72,8 @@ impl Diagnostics {
} }
for diagnostic in &self.items { for diagnostic in &self.items {
let (url, lsp_diagnostic) = to_lsp_diagnostic(db, diagnostic, self.encoding); let (url, lsp_diagnostic) =
to_lsp_diagnostic(db, diagnostic, self.encoding, client_capabilities);
let Some(url) = url else { let Some(url) = url else {
tracing::warn!("Unable to find notebook cell"); tracing::warn!("Unable to find notebook cell");
@ -85,7 +91,9 @@ impl Diagnostics {
LspDiagnostics::TextDocument( LspDiagnostics::TextDocument(
self.items self.items
.iter() .iter()
.map(|diagnostic| to_lsp_diagnostic(db, diagnostic, self.encoding).1) .map(|diagnostic| {
to_lsp_diagnostic(db, diagnostic, self.encoding, client_capabilities).1
})
.collect(), .collect(),
) )
} }
@ -181,7 +189,7 @@ pub(super) fn publish_diagnostics(document: &DocumentHandle, session: &Session,
}); });
}; };
match diagnostics.to_lsp_diagnostics(db) { match diagnostics.to_lsp_diagnostics(db, session.client_capabilities()) {
LspDiagnostics::TextDocument(diagnostics) => { LspDiagnostics::TextDocument(diagnostics) => {
publish_diagnostics_notification(document.url().clone(), diagnostics); publish_diagnostics_notification(document.url().clone(), diagnostics);
} }
@ -212,6 +220,7 @@ pub(crate) fn publish_settings_diagnostics(
} }
let session_encoding = session.position_encoding(); let session_encoding = session.position_encoding();
let client_capabilities = session.client_capabilities();
let state = session.project_state_mut(&AnySystemPath::System(path)); let state = session.project_state_mut(&AnySystemPath::System(path));
let db = &state.db; let db = &state.db;
let project = db.project(); let project = db.project();
@ -253,7 +262,9 @@ pub(crate) fn publish_settings_diagnostics(
// Convert diagnostics to LSP format // Convert diagnostics to LSP format
let lsp_diagnostics = file_diagnostics let lsp_diagnostics = file_diagnostics
.into_iter() .into_iter()
.map(|diagnostic| to_lsp_diagnostic(db, &diagnostic, session_encoding).1) .map(|diagnostic| {
to_lsp_diagnostic(db, &diagnostic, session_encoding, client_capabilities).1
})
.collect::<Vec<_>>(); .collect::<Vec<_>>();
client.send_notification::<PublishDiagnostics>(PublishDiagnosticsParams { client.send_notification::<PublishDiagnostics>(PublishDiagnosticsParams {
@ -292,7 +303,11 @@ pub(super) fn to_lsp_diagnostic(
db: &dyn Db, db: &dyn Db,
diagnostic: &ruff_db::diagnostic::Diagnostic, diagnostic: &ruff_db::diagnostic::Diagnostic,
encoding: PositionEncoding, encoding: PositionEncoding,
client_capabilities: ResolvedClientCapabilities,
) -> (Option<lsp_types::Url>, Diagnostic) { ) -> (Option<lsp_types::Url>, Diagnostic) {
let supports_related_information =
client_capabilities.supports_diagnostic_related_information();
let location = diagnostic.primary_span().and_then(|span| { let location = diagnostic.primary_span().and_then(|span| {
let file = span.expect_ty_file(); let file = span.expect_ty_file();
span.range()? span.range()?
@ -330,13 +345,12 @@ pub(super) fn to_lsp_diagnostic(
Some(CodeDescription { href }) Some(CodeDescription { href })
}); });
let related_information =
if supports_related_information {
let mut related_information = Vec::new(); let mut related_information = Vec::new();
related_information.extend(diagnostic.secondary_annotations().filter_map(
related_information.extend( |annotation| annotation_to_related_information(db, annotation, encoding),
diagnostic ));
.secondary_annotations()
.filter_map(|annotation| annotation_to_related_information(db, annotation, encoding)),
);
for sub_diagnostic in diagnostic.sub_diagnostics() { for sub_diagnostic in diagnostic.sub_diagnostics() {
related_information.extend(sub_diagnostic_to_related_information( related_information.extend(sub_diagnostic_to_related_information(
@ -356,6 +370,11 @@ pub(super) fn to_lsp_diagnostic(
); );
} }
Some(related_information)
} else {
None
};
let data = DiagnosticData::try_from_diagnostic(db, diagnostic, encoding); let data = DiagnosticData::try_from_diagnostic(db, diagnostic, encoding);
( (
@ -367,8 +386,21 @@ pub(super) fn to_lsp_diagnostic(
code: Some(NumberOrString::String(diagnostic.id().to_string())), code: Some(NumberOrString::String(diagnostic.id().to_string())),
code_description, code_description,
source: Some(DIAGNOSTIC_NAME.into()), source: Some(DIAGNOSTIC_NAME.into()),
message: diagnostic.concise_message().to_string(), message: if supports_related_information {
related_information: Some(related_information), // Show both the primary and annotation messages if available,
// because we don't create a related information for the primary message.
if let Some(annotation_message) = diagnostic
.primary_annotation()
.and_then(|annotation| annotation.get_message())
{
format!("{}: {annotation_message}", diagnostic.primary_message())
} else {
diagnostic.primary_message().to_string()
}
} else {
diagnostic.concise_message().to_string()
},
related_information,
data: serde_json::to_value(data).ok(), data: serde_json::to_value(data).ok(),
}, },
) )

View File

@ -59,7 +59,9 @@ impl BackgroundDocumentRequestHandler for DocumentDiagnosticRequestHandler {
result_id: new_id, result_id: new_id,
// SAFETY: Pull diagnostic requests are only called for text documents, not for // SAFETY: Pull diagnostic requests are only called for text documents, not for
// notebook documents. // notebook documents.
items: diagnostics.to_lsp_diagnostics(db).expect_text_document(), items: diagnostics
.to_lsp_diagnostics(db, snapshot.resolved_client_capabilities())
.expect_text_document(),
}, },
}) })
} }

View File

@ -19,6 +19,7 @@ use serde::{Deserialize, Serialize};
use ty_project::{ProgressReporter, ProjectDatabase}; use ty_project::{ProgressReporter, ProjectDatabase};
use crate::PositionEncoding; use crate::PositionEncoding;
use crate::capabilities::ResolvedClientCapabilities;
use crate::document::DocumentKey; use crate::document::DocumentKey;
use crate::server::api::diagnostics::{Diagnostics, to_lsp_diagnostic}; use crate::server::api::diagnostics::{Diagnostics, to_lsp_diagnostic};
use crate::server::api::traits::{ use crate::server::api::traits::{
@ -318,6 +319,7 @@ struct ResponseWriter<'a> {
mode: ReportingMode, mode: ReportingMode,
index: &'a Index, index: &'a Index,
position_encoding: PositionEncoding, position_encoding: PositionEncoding,
client_capabilities: ResolvedClientCapabilities,
// It's important that we use `AnySystemPath` over `Url` here because // It's important that we use `AnySystemPath` over `Url` here because
// `file_to_url` isn't guaranteed to return the exact same URL as the one provided // `file_to_url` isn't guaranteed to return the exact same URL as the one provided
// by the client. // by the client.
@ -357,6 +359,7 @@ impl<'a> ResponseWriter<'a> {
mode, mode,
index, index,
position_encoding, position_encoding,
client_capabilities: snapshot.resolved_client_capabilities(),
previous_result_ids, previous_result_ids,
} }
} }
@ -406,7 +409,15 @@ impl<'a> ResponseWriter<'a> {
new_id => { new_id => {
let lsp_diagnostics = diagnostics let lsp_diagnostics = diagnostics
.iter() .iter()
.map(|diagnostic| to_lsp_diagnostic(db, diagnostic, self.position_encoding).1) .map(|diagnostic| {
to_lsp_diagnostic(
db,
diagnostic,
self.position_encoding,
self.client_capabilities,
)
.1
})
.collect::<Vec<_>>(); .collect::<Vec<_>>();
WorkspaceDocumentDiagnosticReport::Full(WorkspaceFullDocumentDiagnosticReport { WorkspaceDocumentDiagnosticReport::Full(WorkspaceFullDocumentDiagnosticReport {

View File

@ -1103,6 +1103,16 @@ impl TestServerBuilder {
self self
} }
pub(crate) fn enable_diagnostic_related_information(mut self, enabled: bool) -> Self {
self.client_capabilities
.text_document
.get_or_insert_default()
.publish_diagnostics
.get_or_insert_default()
.related_information = Some(enabled);
self
}
/// Set custom client capabilities (overrides any previously set capabilities) /// Set custom client capabilities (overrides any previously set capabilities)
#[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 {

View File

@ -10,6 +10,7 @@ static FILTERS: &[(&str, &str)] = &[(r#""sortText": "[0-9 ]+""#, r#""sortText":
#[test] #[test]
fn publish_diagnostics_open() -> anyhow::Result<()> { fn publish_diagnostics_open() -> anyhow::Result<()> {
let mut server = TestServerBuilder::new()? let mut server = TestServerBuilder::new()?
.enable_diagnostic_related_information(true)
.build() .build()
.wait_until_workspaces_are_initialized(); .wait_until_workspaces_are_initialized();
@ -219,8 +220,7 @@ fn swap_cells() -> anyhow::Result<()> {
"href": "https://ty.dev/rules#unresolved-reference" "href": "https://ty.dev/rules#unresolved-reference"
}, },
"source": "ty", "source": "ty",
"message": "Name `a` used when not defined", "message": "Name `a` used when not defined"
"relatedInformation": []
} }
], ],
"vscode-notebook-cell://src/test.ipynb#1": [], "vscode-notebook-cell://src/test.ipynb#1": [],

View File

@ -30,6 +30,57 @@ def foo() -> str:
Ok(()) Ok(())
} }
#[test]
fn message_without_related_information_support() -> Result<()> {
let workspace_root = SystemPath::new("src");
let foo = SystemPath::new("src/foo.py");
let foo_content = r#"
from typing import assert_type
assert_type("test", list[str])
"#;
let mut server = TestServerBuilder::new()?
.with_workspace(workspace_root, None)?
.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 message_with_related_information_support() -> Result<()> {
let workspace_root = SystemPath::new("src");
let foo = SystemPath::new("src/foo.py");
let foo_content = r#"
from typing import assert_type
assert_type("test", list[str])
"#;
let mut server = TestServerBuilder::new()?
.with_workspace(workspace_root, None)?
.with_file(foo, foo_content)?
.enable_diagnostic_related_information(true)
.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] #[test]
fn on_did_change_watched_files() -> Result<()> { fn on_did_change_watched_files() -> Result<()> {
let workspace_root = SystemPath::new("src"); let workspace_root = SystemPath::new("src");

View File

@ -25,7 +25,6 @@ expression: code_actions
}, },
"source": "ty", "source": "ty",
"message": "Unused `ty: ignore` directive", "message": "Unused `ty: ignore` directive",
"relatedInformation": [],
"tags": [ "tags": [
1 1
] ]
@ -74,7 +73,6 @@ expression: code_actions
}, },
"source": "ty", "source": "ty",
"message": "Unused `ty: ignore` directive", "message": "Unused `ty: ignore` directive",
"relatedInformation": [],
"tags": [ "tags": [
1 1
] ]

View File

@ -24,8 +24,7 @@ expression: code_actions
"href": "https://ty.dev/rules#unresolved-reference" "href": "https://ty.dev/rules#unresolved-reference"
}, },
"source": "ty", "source": "ty",
"message": "Name `typing` used when not defined", "message": "Name `typing` used when not defined"
"relatedInformation": []
} }
], ],
"edit": { "edit": {
@ -70,8 +69,7 @@ expression: code_actions
"href": "https://ty.dev/rules#unresolved-reference" "href": "https://ty.dev/rules#unresolved-reference"
}, },
"source": "ty", "source": "ty",
"message": "Name `typing` used when not defined", "message": "Name `typing` used when not defined"
"relatedInformation": []
} }
], ],
"edit": { "edit": {

View File

@ -24,8 +24,7 @@ expression: code_actions
"href": "https://ty.dev/rules#unresolved-reference" "href": "https://ty.dev/rules#unresolved-reference"
}, },
"source": "ty", "source": "ty",
"message": "Name `deprecated` used when not defined", "message": "Name `deprecated` used when not defined"
"relatedInformation": []
} }
], ],
"edit": { "edit": {
@ -70,8 +69,7 @@ expression: code_actions
"href": "https://ty.dev/rules#unresolved-reference" "href": "https://ty.dev/rules#unresolved-reference"
}, },
"source": "ty", "source": "ty",
"message": "Name `deprecated` used when not defined", "message": "Name `deprecated` used when not defined"
"relatedInformation": []
} }
], ],
"edit": { "edit": {

View File

@ -24,8 +24,7 @@ expression: code_actions
"href": "https://ty.dev/rules#unresolved-reference" "href": "https://ty.dev/rules#unresolved-reference"
}, },
"source": "ty", "source": "ty",
"message": "Name `foobar` used when not defined", "message": "Name `foobar` used when not defined"
"relatedInformation": []
} }
], ],
"edit": { "edit": {

View File

@ -24,8 +24,7 @@ expression: code_actions
"href": "https://ty.dev/rules#possibly-missing-attribute" "href": "https://ty.dev/rules#possibly-missing-attribute"
}, },
"source": "ty", "source": "ty",
"message": "Submodule `parser` may not be available as an attribute on module `html`", "message": "Submodule `parser` may not be available as an attribute on module `html`"
"relatedInformation": []
} }
], ],
"edit": { "edit": {

View File

@ -24,8 +24,7 @@ expression: code_actions
"href": "https://ty.dev/rules#unresolved-reference" "href": "https://ty.dev/rules#unresolved-reference"
}, },
"source": "ty", "source": "ty",
"message": "Name `deprecated` used when not defined", "message": "Name `deprecated` used when not defined"
"relatedInformation": []
} }
], ],
"edit": { "edit": {
@ -70,8 +69,7 @@ expression: code_actions
"href": "https://ty.dev/rules#unresolved-reference" "href": "https://ty.dev/rules#unresolved-reference"
}, },
"source": "ty", "source": "ty",
"message": "Name `deprecated` used when not defined", "message": "Name `deprecated` used when not defined"
"relatedInformation": []
} }
], ],
"edit": { "edit": {

View File

@ -24,8 +24,7 @@ expression: code_actions
"href": "https://ty.dev/rules#unresolved-reference" "href": "https://ty.dev/rules#unresolved-reference"
}, },
"source": "ty", "source": "ty",
"message": "Name `Literal` used when not defined", "message": "Name `Literal` used when not defined"
"relatedInformation": []
} }
], ],
"edit": { "edit": {
@ -70,8 +69,7 @@ expression: code_actions
"href": "https://ty.dev/rules#unresolved-reference" "href": "https://ty.dev/rules#unresolved-reference"
}, },
"source": "ty", "source": "ty",
"message": "Name `Literal` used when not defined", "message": "Name `Literal` used when not defined"
"relatedInformation": []
} }
], ],
"edit": { "edit": {

View File

@ -22,8 +22,7 @@ expression: diagnostics
"href": "https://ty.dev/rules#invalid-return-type" "href": "https://ty.dev/rules#invalid-return-type"
}, },
"source": "ty", "source": "ty",
"message": "Function can implicitly return `None`, which is not assignable to return type `str`", "message": "Function can implicitly return `None`, which is not assignable to return type `str`"
"relatedInformation": []
} }
], ],
"vscode-notebook-cell://test.ipynb#2": [ "vscode-notebook-cell://test.ipynb#2": [
@ -41,8 +40,7 @@ expression: diagnostics
"severity": 1, "severity": 1,
"code": "invalid-syntax", "code": "invalid-syntax",
"source": "ty", "source": "ty",
"message": "Expected `,`, found name", "message": "Expected `,`, found name"
"relatedInformation": []
}, },
{ {
"range": { "range": {
@ -61,8 +59,7 @@ expression: diagnostics
"href": "https://ty.dev/rules#unresolved-reference" "href": "https://ty.dev/rules#unresolved-reference"
}, },
"source": "ty", "source": "ty",
"message": "Name `word` used when not defined", "message": "Name `word` used when not defined"
"relatedInformation": []
}, },
{ {
"range": { "range": {
@ -78,8 +75,7 @@ expression: diagnostics
"severity": 1, "severity": 1,
"code": "invalid-syntax", "code": "invalid-syntax",
"source": "ty", "source": "ty",
"message": "Expected `,`, found string", "message": "Expected `,`, found string"
"relatedInformation": []
}, },
{ {
"range": { "range": {
@ -98,41 +94,7 @@ expression: diagnostics
"href": "https://ty.dev/rules#invalid-argument-type" "href": "https://ty.dev/rules#invalid-argument-type"
}, },
"source": "ty", "source": "ty",
"message": "Argument to function `with_style` is incorrect: Expected `Style`, found `Literal[/", /"]`", "message": "Argument to function `with_style` is incorrect: Expected `Style`, found `Literal[/", /"]`"
"relatedInformation": [
{
"location": {
"uri": "vscode-notebook-cell://test.ipynb#1",
"range": {
"start": {
"line": 0,
"character": 4
},
"end": {
"line": 0,
"character": 14
}
}
},
"message": "Function defined here"
},
{
"location": {
"uri": "vscode-notebook-cell://test.ipynb#1",
"range": {
"start": {
"line": 0,
"character": 32
},
"end": {
"line": 0,
"character": 44
}
}
},
"message": "Parameter declared here"
}
]
}, },
{ {
"range": { "range": {
@ -148,8 +110,7 @@ expression: diagnostics
"severity": 1, "severity": 1,
"code": "invalid-syntax", "code": "invalid-syntax",
"source": "ty", "source": "ty",
"message": "Expected `,`, found name", "message": "Expected `,`, found name"
"relatedInformation": []
}, },
{ {
"range": { "range": {
@ -168,8 +129,7 @@ expression: diagnostics
"href": "https://ty.dev/rules#unresolved-reference" "href": "https://ty.dev/rules#unresolved-reference"
}, },
"source": "ty", "source": "ty",
"message": "Name `underline` used when not defined", "message": "Name `underline` used when not defined"
"relatedInformation": []
}, },
{ {
"range": { "range": {
@ -188,25 +148,7 @@ expression: diagnostics
"href": "https://ty.dev/rules#too-many-positional-arguments" "href": "https://ty.dev/rules#too-many-positional-arguments"
}, },
"source": "ty", "source": "ty",
"message": "Too many positional arguments to function `with_style`: expected 3, got 6", "message": "Too many positional arguments to function `with_style`: expected 3, got 6"
"relatedInformation": [
{
"location": {
"uri": "vscode-notebook-cell://test.ipynb#1",
"range": {
"start": {
"line": 0,
"character": 4
},
"end": {
"line": 0,
"character": 52
}
}
},
"message": "Function signature here"
}
]
}, },
{ {
"range": { "range": {
@ -222,8 +164,7 @@ expression: diagnostics
"severity": 1, "severity": 1,
"code": "invalid-syntax", "code": "invalid-syntax",
"source": "ty", "source": "ty",
"message": "missing closing quote in string literal", "message": "missing closing quote in string literal"
"relatedInformation": []
}, },
{ {
"range": { "range": {
@ -239,8 +180,7 @@ expression: diagnostics
"severity": 1, "severity": 1,
"code": "invalid-syntax", "code": "invalid-syntax",
"source": "ty", "source": "ty",
"message": "Expected `,`, found name", "message": "Expected `,`, found name"
"relatedInformation": []
}, },
{ {
"range": { "range": {
@ -256,8 +196,7 @@ expression: diagnostics
"severity": 1, "severity": 1,
"code": "invalid-syntax", "code": "invalid-syntax",
"source": "ty", "source": "ty",
"message": "unexpected EOF while parsing", "message": "unexpected EOF while parsing"
"relatedInformation": []
} }
] ]
} }

View File

@ -0,0 +1,99 @@
---
source: crates/ty_server/tests/e2e/publish_diagnostics.rs
expression: diagnostics
---
PublishDiagnosticsParams {
uri: Url {
scheme: "file",
cannot_be_a_base: false,
username: "",
password: None,
host: None,
port: None,
path: "<temp_dir>/src/foo.py",
query: None,
fragment: None,
},
diagnostics: [
Diagnostic {
range: Range {
start: Position {
line: 3,
character: 0,
},
end: Position {
line: 3,
character: 30,
},
},
severity: Some(
Error,
),
code: Some(
String(
"type-assertion-failure",
),
),
code_description: Some(
CodeDescription {
href: Url {
scheme: "https",
cannot_be_a_base: false,
username: "",
password: None,
host: Some(
Domain(
"ty.dev",
),
),
port: None,
path: "/rules",
query: None,
fragment: Some(
"type-assertion-failure",
),
},
},
),
source: Some(
"ty",
),
message: "Argument does not have asserted type `list[str]`",
related_information: Some(
[
DiagnosticRelatedInformation {
location: Location {
uri: Url {
scheme: "file",
cannot_be_a_base: false,
username: "",
password: None,
host: None,
port: None,
path: "<temp_dir>/src/foo.py",
query: None,
fragment: None,
},
range: Range {
start: Position {
line: 3,
character: 12,
},
end: Position {
line: 3,
character: 18,
},
},
},
message: "Inferred type is `Literal[/"test/"]`",
},
],
),
tags: None,
data: None,
},
],
version: Some(
1,
),
}

View File

@ -0,0 +1,70 @@
---
source: crates/ty_server/tests/e2e/publish_diagnostics.rs
expression: diagnostics
---
PublishDiagnosticsParams {
uri: Url {
scheme: "file",
cannot_be_a_base: false,
username: "",
password: None,
host: None,
port: None,
path: "<temp_dir>/src/foo.py",
query: None,
fragment: None,
},
diagnostics: [
Diagnostic {
range: Range {
start: Position {
line: 3,
character: 0,
},
end: Position {
line: 3,
character: 30,
},
},
severity: Some(
Error,
),
code: Some(
String(
"type-assertion-failure",
),
),
code_description: Some(
CodeDescription {
href: Url {
scheme: "https",
cannot_be_a_base: false,
username: "",
password: None,
host: Some(
Domain(
"ty.dev",
),
),
port: None,
path: "/rules",
query: None,
fragment: Some(
"type-assertion-failure",
),
},
},
),
source: Some(
"ty",
),
message: "Type `list[str]` does not match asserted type `Literal[/"test/"]`",
related_information: None,
tags: None,
data: None,
},
],
version: Some(
1,
),
}

View File

@ -59,36 +59,7 @@ PublishDiagnosticsParams {
"ty", "ty",
), ),
message: "Return type does not match returned value: expected `str`, found `Literal[42]`", message: "Return type does not match returned value: expected `str`, found `Literal[42]`",
related_information: Some( related_information: None,
[
DiagnosticRelatedInformation {
location: Location {
uri: Url {
scheme: "file",
cannot_be_a_base: false,
username: "",
password: None,
host: None,
port: None,
path: "<temp_dir>/src/foo.py",
query: None,
fragment: None,
},
range: Range {
start: Position {
line: 0,
character: 13,
},
end: Position {
line: 0,
character: 16,
},
},
},
message: "Expected `str` because of return type",
},
],
),
tags: None, tags: None,
data: None, data: None,
}, },

View File

@ -55,36 +55,7 @@ Report(
"ty", "ty",
), ),
message: "Return type does not match returned value: expected `str`, found `Literal[42]`", message: "Return type does not match returned value: expected `str`, found `Literal[42]`",
related_information: Some( related_information: None,
[
DiagnosticRelatedInformation {
location: Location {
uri: Url {
scheme: "file",
cannot_be_a_base: false,
username: "",
password: None,
host: None,
port: None,
path: "<temp_dir>/src/foo.py",
query: None,
fragment: None,
},
range: Range {
start: Position {
line: 0,
character: 13,
},
end: Position {
line: 0,
character: 16,
},
},
},
message: "Expected `str` because of return type",
},
],
),
tags: None, tags: None,
data: None, data: None,
}, },

View File

@ -70,36 +70,7 @@ Report(
"ty", "ty",
), ),
message: "Return type does not match returned value: expected `int`, found `Literal[/"hello/"]`", message: "Return type does not match returned value: expected `int`, found `Literal[/"hello/"]`",
related_information: Some( related_information: None,
[
DiagnosticRelatedInformation {
location: Location {
uri: Url {
scheme: "file",
cannot_be_a_base: false,
username: "",
password: None,
host: None,
port: None,
path: "<temp_dir>/src/changed_error.py",
query: None,
fragment: None,
},
range: Range {
start: Position {
line: 0,
character: 13,
},
end: Position {
line: 0,
character: 16,
},
},
},
message: "Expected `int` because of return type",
},
],
),
tags: None, tags: None,
data: None, data: None,
}, },
@ -194,36 +165,7 @@ Report(
"ty", "ty",
), ),
message: "Return type does not match returned value: expected `str`, found `Literal[42]`", message: "Return type does not match returned value: expected `str`, found `Literal[42]`",
related_information: Some( related_information: None,
[
DiagnosticRelatedInformation {
location: Location {
uri: Url {
scheme: "file",
cannot_be_a_base: false,
username: "",
password: None,
host: None,
port: None,
path: "<temp_dir>/src/modified_same_error.py",
query: None,
fragment: None,
},
range: Range {
start: Position {
line: 3,
character: 13,
},
end: Position {
line: 3,
character: 16,
},
},
},
message: "Expected `str` because of return type",
},
],
),
tags: None, tags: None,
data: None, data: None,
}, },
@ -296,36 +238,7 @@ Report(
"ty", "ty",
), ),
message: "Return type does not match returned value: expected `str`, found `Literal[42]`", message: "Return type does not match returned value: expected `str`, found `Literal[42]`",
related_information: Some( related_information: None,
[
DiagnosticRelatedInformation {
location: Location {
uri: Url {
scheme: "file",
cannot_be_a_base: false,
username: "",
password: None,
host: None,
port: None,
path: "<temp_dir>/src/new_error.py",
query: None,
fragment: None,
},
range: Range {
start: Position {
line: 0,
character: 13,
},
end: Position {
line: 0,
character: 16,
},
},
},
message: "Expected `str` because of return type",
},
],
),
tags: None, tags: None,
data: None, data: None,
}, },

View File

@ -68,36 +68,7 @@ Report(
"ty", "ty",
), ),
message: "Return type does not match returned value: expected `str`, found `Literal[42]`", message: "Return type does not match returned value: expected `str`, found `Literal[42]`",
related_information: Some( related_information: None,
[
DiagnosticRelatedInformation {
location: Location {
uri: Url {
scheme: "file",
cannot_be_a_base: false,
username: "",
password: None,
host: None,
port: None,
path: "<temp_dir>/src/changed_error.py",
query: None,
fragment: None,
},
range: Range {
start: Position {
line: 0,
character: 13,
},
end: Position {
line: 0,
character: 16,
},
},
},
message: "Expected `str` because of return type",
},
],
),
tags: None, tags: None,
data: None, data: None,
}, },
@ -168,36 +139,7 @@ Report(
"ty", "ty",
), ),
message: "Return type does not match returned value: expected `str`, found `Literal[42]`", message: "Return type does not match returned value: expected `str`, found `Literal[42]`",
related_information: Some( related_information: None,
[
DiagnosticRelatedInformation {
location: Location {
uri: Url {
scheme: "file",
cannot_be_a_base: false,
username: "",
password: None,
host: None,
port: None,
path: "<temp_dir>/src/fixed_error.py",
query: None,
fragment: None,
},
range: Range {
start: Position {
line: 0,
character: 13,
},
end: Position {
line: 0,
character: 16,
},
},
},
message: "Expected `str` because of return type",
},
],
),
tags: None, tags: None,
data: None, data: None,
}, },
@ -268,36 +210,7 @@ Report(
"ty", "ty",
), ),
message: "Return type does not match returned value: expected `str`, found `Literal[42]`", message: "Return type does not match returned value: expected `str`, found `Literal[42]`",
related_information: Some( related_information: None,
[
DiagnosticRelatedInformation {
location: Location {
uri: Url {
scheme: "file",
cannot_be_a_base: false,
username: "",
password: None,
host: None,
port: None,
path: "<temp_dir>/src/modified_same_error.py",
query: None,
fragment: None,
},
range: Range {
start: Position {
line: 0,
character: 13,
},
end: Position {
line: 0,
character: 16,
},
},
},
message: "Expected `str` because of return type",
},
],
),
tags: None, tags: None,
data: None, data: None,
}, },
@ -370,36 +283,7 @@ Report(
"ty", "ty",
), ),
message: "Return type does not match returned value: expected `str`, found `Literal[42]`", message: "Return type does not match returned value: expected `str`, found `Literal[42]`",
related_information: Some( related_information: None,
[
DiagnosticRelatedInformation {
location: Location {
uri: Url {
scheme: "file",
cannot_be_a_base: false,
username: "",
password: None,
host: None,
port: None,
path: "<temp_dir>/src/unchanged.py",
query: None,
fragment: None,
},
range: Range {
start: Position {
line: 0,
character: 13,
},
end: Position {
line: 0,
character: 16,
},
},
},
message: "Expected `str` because of return type",
},
],
),
tags: None, tags: None,
data: None, data: None,
}, },

View File

@ -70,36 +70,7 @@ Report(
"ty", "ty",
), ),
message: "Return type does not match returned value: expected `str`, found `Literal[42]`", message: "Return type does not match returned value: expected `str`, found `Literal[42]`",
related_information: Some( related_information: None,
[
DiagnosticRelatedInformation {
location: Location {
uri: Url {
scheme: "file",
cannot_be_a_base: false,
username: "",
password: None,
host: None,
port: None,
path: "<temp_dir>/src/test.py",
query: None,
fragment: None,
},
range: Range {
start: Position {
line: 0,
character: 15,
},
end: Position {
line: 0,
character: 18,
},
},
},
message: "Expected `str` because of return type",
},
],
),
tags: None, tags: None,
data: None, data: None,
}, },

View File

@ -68,9 +68,7 @@ expression: all_items
"ty", "ty",
), ),
message: "Name `true` used when not defined", message: "Name `true` used when not defined",
related_information: Some( related_information: None,
[],
),
tags: None, tags: None,
data: None, data: None,
}, },
@ -143,9 +141,7 @@ expression: all_items
"ty", "ty",
), ),
message: "Name `true` used when not defined", message: "Name `true` used when not defined",
related_information: Some( related_information: None,
[],
),
tags: None, tags: None,
data: None, data: None,
}, },
@ -218,9 +214,7 @@ expression: all_items
"ty", "ty",
), ),
message: "Name `true` used when not defined", message: "Name `true` used when not defined",
related_information: Some( related_information: None,
[],
),
tags: None, tags: None,
data: None, data: None,
}, },

View File

@ -70,36 +70,7 @@ Report(
"ty", "ty",
), ),
message: "Return type does not match returned value: expected `str`, found `Literal[42]`", message: "Return type does not match returned value: expected `str`, found `Literal[42]`",
related_information: Some( related_information: None,
[
DiagnosticRelatedInformation {
location: Location {
uri: Url {
scheme: "file",
cannot_be_a_base: false,
username: "",
password: None,
host: None,
port: None,
path: "<temp_dir>/src/test.py",
query: None,
fragment: None,
},
range: Range {
start: Position {
line: 0,
character: 15,
},
end: Position {
line: 0,
character: 18,
},
},
},
message: "Expected `str` because of return type",
},
],
),
tags: None, tags: None,
data: None, data: None,
}, },