add diagnostic Span (couples File and TextRange)#16101
Conversation
|
MichaReiser
left a comment
There was a problem hiding this comment.
Nice: The only thing that's unclear to me is whether we want to store Spans directly on the concrete Diagnostic types or if we want to construct the span ad-hoc in the span method. I think I'm fine with either.
|
|
||
| fn range(&self) -> Option<TextRange> { | ||
| Some(Ranged::range(self)) | ||
| fn span(&self) -> Option<Span> { |
There was a problem hiding this comment.
Same: I'm sort of inclined to simply store the Span directly on the Diagnostic struct. But I guess this way is fine too
There was a problem hiding this comment.
This one is a little trickier because a TypedDiagnostic always has a File and a Range, where as a Span always has a File and an optional Range. So I'm going to leave this as-is for now.
This is a small change to facilitate migrating to a trait without separate `file` and `range` methods.
... in favor of the implementations providing this routine themselves.
... and update all of the consumers to use `Diagnostic::span`.
95ec2f4 to
1266c26
Compare
AlexWaygood
left a comment
There was a problem hiding this comment.
Since Span is Copy, you could make the range and file methods take self rather than &self, which would allow you to get rid of a few closures:
Patch
diff --git a/crates/red_knot_project/src/lib.rs b/crates/red_knot_project/src/lib.rs
index 2126f36a8..bd3dfe60a 100644
--- a/crates/red_knot_project/src/lib.rs
+++ b/crates/red_knot_project/src/lib.rs
@@ -347,7 +347,7 @@ fn check_file_impl(db: &dyn Db, file: File) -> Vec<Box<dyn Diagnostic>> {
diagnostics.sort_unstable_by_key(|diagnostic| {
diagnostic
.span()
- .and_then(|span| span.range())
+ .and_then(Span::range)
.unwrap_or_default()
.start()
});
diff --git a/crates/red_knot_test/src/diagnostic.rs b/crates/red_knot_test/src/diagnostic.rs
index 56ee51223..7cf258f11 100644
--- a/crates/red_knot_test/src/diagnostic.rs
+++ b/crates/red_knot_test/src/diagnostic.rs
@@ -2,7 +2,7 @@
//!
//! We don't assume that we will get the diagnostics in source order.
-use ruff_db::diagnostic::Diagnostic;
+use ruff_db::diagnostic::{Diagnostic, Span};
use ruff_source_file::{LineIndex, OneIndexed};
use std::ops::{Deref, Range};
@@ -27,7 +27,7 @@ where
.map(|diagnostic| DiagnosticWithLine {
line_number: diagnostic
.span()
- .and_then(|span| span.range())
+ .and_then(Span::range)
.map_or(OneIndexed::from_zero_indexed(0), |range| {
line_index.line_index(range.start())
}),
diff --git a/crates/red_knot_test/src/matcher.rs b/crates/red_knot_test/src/matcher.rs
index d350ec7c6..d90bcef03 100644
--- a/crates/red_knot_test/src/matcher.rs
+++ b/crates/red_knot_test/src/matcher.rs
@@ -4,7 +4,7 @@ use crate::assertion::{Assertion, ErrorAssertion, InlineFileAssertions};
use crate::db::Db;
use crate::diagnostic::SortedDiagnostics;
use colored::Colorize;
-use ruff_db::diagnostic::{Diagnostic, DiagnosticAsStrError, DiagnosticId};
+use ruff_db::diagnostic::{Diagnostic, DiagnosticAsStrError, DiagnosticId, Span};
use ruff_db::files::File;
use ruff_db::source::{line_index, source_text, SourceText};
use ruff_source_file::{LineIndex, OneIndexed};
@@ -258,7 +258,7 @@ impl Matcher {
fn column<T: Diagnostic>(&self, diagnostic: &T) -> OneIndexed {
diagnostic
.span()
- .and_then(|span| span.range())
+ .and_then(Span::range)
.map(|range| {
self.line_index
.source_location(range.start(), &self.source)
diff --git a/crates/ruff_benchmark/benches/red_knot.rs b/crates/ruff_benchmark/benches/red_knot.rs
index 87366b04d..423446dde 100644
--- a/crates/ruff_benchmark/benches/red_knot.rs
+++ b/crates/ruff_benchmark/benches/red_knot.rs
@@ -11,7 +11,7 @@ use red_knot_project::{Db, ProjectDatabase, ProjectMetadata};
use red_knot_python_semantic::PythonVersion;
use ruff_benchmark::criterion::{criterion_group, criterion_main, BatchSize, Criterion};
use ruff_benchmark::TestFile;
-use ruff_db::diagnostic::{Diagnostic, DiagnosticId, Severity};
+use ruff_db::diagnostic::{Diagnostic, DiagnosticId, Severity, Span};
use ruff_db::files::{system_path_to_file, File};
use ruff_db::source::source_text;
use ruff_db::system::{MemoryFileSystem, SystemPath, SystemPathBuf, TestSystem};
@@ -231,11 +231,11 @@ fn assert_diagnostics(db: &dyn Db, diagnostics: &[Box<dyn Diagnostic>]) {
diagnostic.id(),
diagnostic
.span()
- .map(|span| span.file())
+ .map(Span::file)
.map(|file| file.path(db).as_str()),
diagnostic
.span()
- .and_then(|span| span.range())
+ .and_then(Span::range)
.map(Range::<usize>::from),
diagnostic.message(),
diagnostic.severity(),
diff --git a/crates/ruff_db/src/diagnostic.rs b/crates/ruff_db/src/diagnostic.rs
index 02c701267..5bcec79c5 100644
--- a/crates/ruff_db/src/diagnostic.rs
+++ b/crates/ruff_db/src/diagnostic.rs
@@ -196,7 +196,7 @@ pub struct Span {
impl Span {
/// Returns the `File` attached to this `Span`.
- pub fn file(&self) -> File {
+ pub fn file(self) -> File {
self.file
}
@@ -205,7 +205,7 @@ impl Span {
/// When there is no range, it is convention to assume that this `Span`
/// refers to the corresponding `File` as a whole. In some cases, consumers
/// of this API may use the range `0..0` to represent this case.
- pub fn range(&self) -> Option<TextRange> {
+ pub fn range(self) -> Option<TextRange> {
self.range
}(No strong opinion on whether that's worth it, though)
|
It's unclear if |
|
Yeah I'm going to remove the |
I think ideally this type would be `Copy`, but it sounds like that might prove difficult for Ruff since it doesn't have a `Copy` file handle.
|
I could see us interning files in Ruff when we create the diagnostics, but yeah, it's somewhat unclear if that's hard. But definitely annoying if |
* main: add diagnostic `Span` (couples `File` and `TextRange`) (#16101) Remove `Hash` and `Eq` from `AstNodeRef` for types not implementing `Eq` or `Hash` (#16100) Fix release build warning about unused todo type message (#16102) [`pydocstyle`] Handle arguments with the same names as sections (`D417`) (#16011) [red-knot] Reduce usage of `From<Type>` implementations when working with `Symbol`s (#16076) Transition to salsa coarse-grained tracked structs (#15763) [`pyupgrade`] Handle micro version numbers correctly (`UP036`) (#16091) [red-knot] `T | object == object` (#16088) [`ruff`] Skip singleton starred expressions for `incorrectly-parenthesized-tuple-in-subscript` (`RUF031`) (#16083) Delete left-over `verbosity.rs (#16081) [red-knot] User-level configuration (#16021) Add `user_configuration_directory` to `System` (#16020)
This essentially makes it impossible to construct a
Diagnosticthat has a
TextRangebut noFile.This is meant to be a precursor to multi-span support.
(Note that I consider this more of a prototyping-change and not
necessarily what this is going to look like longer term.)
Reviewers can probably review this PR as one big diff instead of
commit-by-commit.