[red-knot] Make `Diagnostic::file` optional (#15640)

This commit is contained in:
Micha Reiser 2025-01-23 10:43:14 +01:00 committed by GitHub
parent 1ecd97855e
commit 23c222368e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 36 additions and 26 deletions

View File

@ -402,8 +402,8 @@ impl Diagnostic for IOErrorDiagnostic {
self.error.to_string().into() self.error.to_string().into()
} }
fn file(&self) -> File { fn file(&self) -> Option<File> {
self.file Some(self.file)
} }
fn range(&self) -> Option<TextRange> { fn range(&self) -> Option<TextRange> {

View File

@ -5,6 +5,7 @@ use red_knot_python_semantic::{
use ruff_db::system::{System, SystemPath}; use ruff_db::system::{System, SystemPath};
use ruff_macros::Combine; use ruff_macros::Combine;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::fmt::Debug;
use thiserror::Error; use thiserror::Error;
/// The options for the project. /// The options for the project.

View File

@ -802,8 +802,8 @@ impl Diagnostic for TypeCheckDiagnostic {
TypeCheckDiagnostic::message(self).into() TypeCheckDiagnostic::message(self).into()
} }
fn file(&self) -> File { fn file(&self) -> Option<File> {
TypeCheckDiagnostic::file(self) Some(TypeCheckDiagnostic::file(self))
} }
fn range(&self) -> Option<TextRange> { fn range(&self) -> Option<TextRange> {

View File

@ -75,9 +75,9 @@ fn to_lsp_diagnostic(
diagnostic: &dyn ruff_db::diagnostic::Diagnostic, diagnostic: &dyn ruff_db::diagnostic::Diagnostic,
encoding: crate::PositionEncoding, encoding: crate::PositionEncoding,
) -> Diagnostic { ) -> Diagnostic {
let range = if let Some(range) = diagnostic.range() { let range = if let (Some(file), Some(range)) = (diagnostic.file(), diagnostic.range()) {
let index = line_index(db.upcast(), diagnostic.file()); let index = line_index(db.upcast(), file);
let source = source_text(db.upcast(), diagnostic.file()); let source = source_text(db.upcast(), file);
range.to_range(&source, &index, encoding) range.to_range(&source, &index, encoding)
} else { } else {

View File

@ -198,8 +198,8 @@ mod tests {
"dummy".into() "dummy".into()
} }
fn file(&self) -> File { fn file(&self) -> Option<File> {
self.file Some(self.file)
} }
fn range(&self) -> Option<TextRange> { fn range(&self) -> Option<TextRange> {

View File

@ -385,8 +385,8 @@ mod tests {
self.message.into() self.message.into()
} }
fn file(&self) -> File { fn file(&self) -> Option<File> {
self.file Some(self.file)
} }
fn range(&self) -> Option<TextRange> { fn range(&self) -> Option<TextRange> {

View File

@ -152,8 +152,18 @@ pub trait Diagnostic: Send + Sync + std::fmt::Debug {
fn message(&self) -> Cow<str>; fn message(&self) -> Cow<str>;
fn file(&self) -> File; /// The file this diagnostic is associated with.
///
/// File can be `None` for diagnostics that don't originate from a file.
/// For example:
/// * A diagnostic indicating that a directory couldn't be read.
/// * A diagnostic related to a CLI argument
fn file(&self) -> Option<File>;
/// The primary range of the diagnostic in `file`.
///
/// The range can be `None` if the diagnostic doesn't have a file
/// or it applies to the entire file (e.g. the file should be executable but isn't).
fn range(&self) -> Option<TextRange>; fn range(&self) -> Option<TextRange>;
fn severity(&self) -> Severity; fn severity(&self) -> Severity;
@ -197,16 +207,15 @@ impl std::fmt::Display for DisplayDiagnostic<'_> {
Severity::Fatal => f.write_str("fatal")?, Severity::Fatal => f.write_str("fatal")?,
} }
write!( write!(f, "[{rule}]", rule = self.diagnostic.id())?;
f,
"[{rule}] {path}",
rule = self.diagnostic.id(),
path = self.diagnostic.file().path(self.db)
)?;
if let Some(range) = self.diagnostic.range() { if let Some(file) = self.diagnostic.file() {
let index = line_index(self.db, self.diagnostic.file()); write!(f, " {path}", path = file.path(self.db))?;
let source = source_text(self.db, self.diagnostic.file()); }
if let (Some(file), Some(range)) = (self.diagnostic.file(), self.diagnostic.range()) {
let index = line_index(self.db, file);
let source = source_text(self.db, file);
let start = index.source_location(range.start(), &source); let start = index.source_location(range.start(), &source);
@ -229,7 +238,7 @@ where
(**self).message() (**self).message()
} }
fn file(&self) -> File { fn file(&self) -> Option<File> {
(**self).file() (**self).file()
} }
@ -254,7 +263,7 @@ where
(**self).message() (**self).message()
} }
fn file(&self) -> File { fn file(&self) -> Option<File> {
(**self).file() (**self).file()
} }
@ -276,7 +285,7 @@ impl Diagnostic for Box<dyn Diagnostic> {
(**self).message() (**self).message()
} }
fn file(&self) -> File { fn file(&self) -> Option<File> {
(**self).file() (**self).file()
} }
@ -310,8 +319,8 @@ impl Diagnostic for ParseDiagnostic {
self.error.error.to_string().into() self.error.error.to_string().into()
} }
fn file(&self) -> File { fn file(&self) -> Option<File> {
self.file Some(self.file)
} }
fn range(&self) -> Option<TextRange> { fn range(&self) -> Option<TextRange> {