Skip to content

Commit 8a027bb

Browse files
committed
[WIP] Hide empty snippets for full-file diagnostics
Summary -- This isn't really polished for review yet, but this is the other commit I wanted to spin off from #19415. This suppresses empty snippets for empty ranges at the very beginning of a file, and for empty ranges in non-existent files. Ruff includes empty ranges for IO errors, for example. Test Plan -- TODO add a `ruff_db` test with an example
1 parent 1e1bd62 commit 8a027bb

File tree

5 files changed

+47
-4
lines changed

5 files changed

+47
-4
lines changed

crates/ruff_annotate_snippets/src/renderer/display_list.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1164,6 +1164,16 @@ fn format_snippet<'m>(
11641164
let main_range = snippet.annotations.first().map(|x| x.range.start);
11651165
let origin = snippet.origin;
11661166
let need_empty_header = origin.is_some() || is_first;
1167+
1168+
let is_file_level = snippet.annotations.iter().any(|ann| ann.is_file_level);
1169+
if is_file_level {
1170+
let header = format_header(origin, main_range, &[], is_first);
1171+
return DisplaySet {
1172+
display_lines: header.map_or_else(Vec::new, |header| vec![header]),
1173+
margin: Margin::new(0, 0, 0, 0, term_width, 0),
1174+
};
1175+
}
1176+
11671177
let mut body = format_body(
11681178
snippet,
11691179
need_empty_header,

crates/ruff_annotate_snippets/src/snippet.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,13 +114,19 @@ pub struct Annotation<'a> {
114114
pub(crate) range: Range<usize>,
115115
pub(crate) label: Option<&'a str>,
116116
pub(crate) level: Level,
117+
pub(crate) is_file_level: bool,
117118
}
118119

119120
impl<'a> Annotation<'a> {
120121
pub fn label(mut self, label: &'a str) -> Self {
121122
self.label = Some(label);
122123
self
123124
}
125+
126+
pub fn is_file_level(mut self, yes: bool) -> Self {
127+
self.is_file_level = yes;
128+
self
129+
}
124130
}
125131

126132
/// Types of annotations.
@@ -154,6 +160,7 @@ impl Level {
154160
range: span,
155161
label: None,
156162
level: self,
163+
is_file_level: false,
157164
}
158165
}
159166
}

crates/ruff_db/src/diagnostic/mod.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -702,6 +702,11 @@ pub struct Annotation {
702702
is_primary: bool,
703703
/// The diagnostic tags associated with this annotation.
704704
tags: Vec<DiagnosticTag>,
705+
/// Whether this annotation is a file-level or full-file annotation.
706+
///
707+
/// When set, rendering will not include a file snippet but will still have the file's name and
708+
/// (optional) range.
709+
is_file_level: bool,
705710
}
706711

707712
impl Annotation {
@@ -720,6 +725,7 @@ impl Annotation {
720725
message: None,
721726
is_primary: true,
722727
tags: Vec::new(),
728+
is_file_level: false,
723729
}
724730
}
725731

@@ -736,6 +742,7 @@ impl Annotation {
736742
message: None,
737743
is_primary: false,
738744
tags: Vec::new(),
745+
is_file_level: false,
739746
}
740747
}
741748

@@ -801,6 +808,10 @@ impl Annotation {
801808
pub fn push_tag(&mut self, tag: DiagnosticTag) {
802809
self.tags.push(tag);
803810
}
811+
812+
pub fn set_file_level(&mut self, yes: bool) {
813+
self.is_file_level = yes;
814+
}
804815
}
805816

806817
/// Tags that can be associated with an annotation.

crates/ruff_db/src/diagnostic/render.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -389,6 +389,7 @@ struct ResolvedAnnotation<'a> {
389389
line_end: OneIndexed,
390390
message: Option<&'a str>,
391391
is_primary: bool,
392+
is_file_level: bool,
392393
}
393394

394395
impl<'a> ResolvedAnnotation<'a> {
@@ -434,6 +435,7 @@ impl<'a> ResolvedAnnotation<'a> {
434435
line_end,
435436
message: ann.get_message(),
436437
is_primary: ann.is_primary,
438+
is_file_level: ann.is_file_level,
437439
})
438440
}
439441
}
@@ -651,6 +653,8 @@ struct RenderableAnnotation<'r> {
651653
message: Option<&'r str>,
652654
/// Whether this annotation is considered "primary" or not.
653655
is_primary: bool,
656+
/// Whether this annotation applies to an entire file, rather than a snippet within it.
657+
is_file_level: bool,
654658
}
655659

656660
impl<'r> RenderableAnnotation<'r> {
@@ -668,6 +672,7 @@ impl<'r> RenderableAnnotation<'r> {
668672
range,
669673
message: ann.message,
670674
is_primary: ann.is_primary,
675+
is_file_level: ann.is_file_level,
671676
}
672677
}
673678

@@ -693,7 +698,7 @@ impl<'r> RenderableAnnotation<'r> {
693698
if let Some(message) = self.message {
694699
ann = ann.label(message);
695700
}
696-
ann
701+
ann.is_file_level(self.is_file_level)
697702
}
698703
}
699704

crates/ruff_linter/src/message/mod.rs

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,14 @@ pub fn create_syntax_error_diagnostic(
4848
Severity::Error,
4949
format_args!("SyntaxError: {message}"),
5050
);
51-
let span = span.into().with_range(range.range());
52-
diag.annotate(Annotation::primary(span));
51+
let range = range.range();
52+
let span = span.into().with_range(range);
53+
let mut annotation = Annotation::primary(span);
54+
// The `0..0` range is used to highlight file-level diagnostics.
55+
if range == TextRange::default() {
56+
annotation.set_file_level(true);
57+
}
58+
diag.annotate(annotation);
5359
diag
5460
}
5561

@@ -75,7 +81,11 @@ where
7581
);
7682

7783
let span = Span::from(file).with_range(range);
78-
let annotation = Annotation::primary(span);
84+
let mut annotation = Annotation::primary(span);
85+
// The `0..0` range is used to highlight file-level diagnostics.
86+
if range == TextRange::default() {
87+
annotation.set_file_level(true);
88+
}
7989
diagnostic.annotate(annotation);
8090

8191
if let Some(suggestion) = suggestion {

0 commit comments

Comments
 (0)