Skip to content

Commit 8484b99

Browse files
authored
Rollup merge of #72026 - botika:master, r=estebank
Update annotate-snippets-rs to 0.8.0 #59346 I made major changes to this library. In the previous version we worked with owned while in the current one with borrowed. I have adapted it without changing the behavior. I have modified the coverage since the previous one did not return correctly the index of the character in the line.
2 parents 7355816 + 8fc6202 commit 8484b99

File tree

7 files changed

+210
-128
lines changed

7 files changed

+210
-128
lines changed

Diff for: Cargo.lock

+9-3
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,12 @@ dependencies = [
4848
"ansi_term",
4949
]
5050

51+
[[package]]
52+
name = "annotate-snippets"
53+
version = "0.8.0"
54+
source = "registry+https://github.com/rust-lang/crates.io-index"
55+
checksum = "d78ea013094e5ea606b1c05fe35f1dd7ea1eb1ea259908d040b25bd5ec677ee5"
56+
5157
[[package]]
5258
name = "ansi_term"
5359
version = "0.11.0"
@@ -3316,7 +3322,7 @@ version = "659.0.0"
33163322
source = "registry+https://github.com/rust-lang/crates.io-index"
33173323
checksum = "0c374e89b3c9714869ef86076942155383804ba6778c26be2169d324563c31f9"
33183324
dependencies = [
3319-
"annotate-snippets",
3325+
"annotate-snippets 0.6.1",
33203326
"atty",
33213327
"log",
33223328
"rustc-ap-rustc_data_structures",
@@ -3810,7 +3816,7 @@ version = "0.0.0"
38103816
name = "rustc_errors"
38113817
version = "0.0.0"
38123818
dependencies = [
3813-
"annotate-snippets",
3819+
"annotate-snippets 0.8.0",
38143820
"atty",
38153821
"log",
38163822
"rustc_data_structures",
@@ -4477,7 +4483,7 @@ dependencies = [
44774483
name = "rustfmt-nightly"
44784484
version = "1.4.15"
44794485
dependencies = [
4480-
"annotate-snippets",
4486+
"annotate-snippets 0.6.1",
44814487
"bytecount",
44824488
"cargo_metadata 0.8.0",
44834489
"derive-new",

Diff for: src/librustc_errors/Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ rustc_data_structures = { path = "../librustc_data_structures" }
1717
unicode-width = "0.1.4"
1818
atty = "0.2"
1919
termcolor = "1.0"
20-
annotate-snippets = "0.6.1"
20+
annotate-snippets = "0.8.0"
2121
termize = "0.1.1"
2222

2323
[target.'cfg(windows)'.dependencies]

Diff for: src/librustc_errors/annotate_snippet_emitter_writer.rs

+92-123
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,11 @@
88
use crate::emitter::FileWithAnnotatedLines;
99
use crate::snippet::Line;
1010
use crate::{CodeSuggestion, Diagnostic, DiagnosticId, Emitter, Level, SubDiagnostic};
11-
use annotate_snippets::display_list::DisplayList;
12-
use annotate_snippets::formatter::DisplayListFormatter;
11+
use annotate_snippets::display_list::{DisplayList, FormatOptions};
1312
use annotate_snippets::snippet::*;
1413
use rustc_data_structures::sync::Lrc;
1514
use rustc_span::source_map::SourceMap;
16-
use rustc_span::{Loc, MultiSpan, SourceFile};
15+
use rustc_span::{MultiSpan, SourceFile};
1716

1817
/// Generates diagnostics using annotate-snippet
1918
pub struct AnnotateSnippetEmitterWriter {
@@ -59,112 +58,20 @@ impl Emitter for AnnotateSnippetEmitterWriter {
5958
}
6059
}
6160

62-
/// Collects all the data needed to generate the data structures needed for the
63-
/// `annotate-snippets` library.
64-
struct DiagnosticConverter<'a> {
65-
source_map: Option<Lrc<SourceMap>>,
66-
level: Level,
67-
message: String,
68-
code: Option<DiagnosticId>,
69-
msp: MultiSpan,
70-
#[allow(dead_code)]
71-
children: &'a [SubDiagnostic],
72-
#[allow(dead_code)]
73-
suggestions: &'a [CodeSuggestion],
61+
/// Provides the source string for the given `line` of `file`
62+
fn source_string(file: Lrc<SourceFile>, line: &Line) -> String {
63+
file.get_line(line.line_index - 1).map(|a| a.to_string()).unwrap_or_default()
7464
}
7565

76-
impl<'a> DiagnosticConverter<'a> {
77-
/// Turns rustc Diagnostic information into a `annotate_snippets::snippet::Snippet`.
78-
fn to_annotation_snippet(&self) -> Option<Snippet> {
79-
if let Some(source_map) = &self.source_map {
80-
// Make sure our primary file comes first
81-
let primary_lo = if let Some(ref primary_span) = self.msp.primary_span().as_ref() {
82-
source_map.lookup_char_pos(primary_span.lo())
83-
} else {
84-
// FIXME(#59346): Not sure when this is the case and what
85-
// should be done if it happens
86-
return None;
87-
};
88-
let annotated_files =
89-
FileWithAnnotatedLines::collect_annotations(&self.msp, &self.source_map);
90-
let slices = self.slices_for_files(annotated_files, primary_lo);
91-
92-
Some(Snippet {
93-
title: Some(Annotation {
94-
label: Some(self.message.to_string()),
95-
id: self.code.clone().map(|c| match c {
96-
DiagnosticId::Error(val) | DiagnosticId::Lint(val) => val,
97-
}),
98-
annotation_type: Self::annotation_type_for_level(self.level),
99-
}),
100-
footer: vec![],
101-
slices,
102-
})
103-
} else {
104-
// FIXME(#59346): Is it ok to return None if there's no source_map?
105-
None
106-
}
107-
}
108-
109-
fn slices_for_files(
110-
&self,
111-
annotated_files: Vec<FileWithAnnotatedLines>,
112-
primary_lo: Loc,
113-
) -> Vec<Slice> {
114-
// FIXME(#64205): Provide a test case where `annotated_files` is > 1
115-
annotated_files
116-
.iter()
117-
.flat_map(|annotated_file| {
118-
annotated_file
119-
.lines
120-
.iter()
121-
.map(|line| {
122-
let line_source = Self::source_string(annotated_file.file.clone(), &line);
123-
Slice {
124-
source: line_source,
125-
line_start: line.line_index,
126-
origin: Some(primary_lo.file.name.to_string()),
127-
// FIXME(#59346): Not really sure when `fold` should be true or false
128-
fold: false,
129-
annotations: line
130-
.annotations
131-
.iter()
132-
.map(|a| self.annotation_to_source_annotation(a.clone()))
133-
.collect(),
134-
}
135-
})
136-
.collect::<Vec<Slice>>()
137-
})
138-
.collect::<Vec<Slice>>()
139-
}
140-
141-
/// Turns a `crate::snippet::Annotation` into a `SourceAnnotation`
142-
fn annotation_to_source_annotation(
143-
&self,
144-
annotation: crate::snippet::Annotation,
145-
) -> SourceAnnotation {
146-
SourceAnnotation {
147-
range: (annotation.start_col, annotation.end_col),
148-
label: annotation.label.unwrap_or("".to_string()),
149-
annotation_type: Self::annotation_type_for_level(self.level),
150-
}
151-
}
152-
153-
/// Provides the source string for the given `line` of `file`
154-
fn source_string(file: Lrc<SourceFile>, line: &Line) -> String {
155-
file.get_line(line.line_index - 1).map(|a| a.to_string()).unwrap_or(String::new())
156-
}
157-
158-
/// Maps `Diagnostic::Level` to `snippet::AnnotationType`
159-
fn annotation_type_for_level(level: Level) -> AnnotationType {
160-
match level {
161-
Level::Bug | Level::Fatal | Level::Error => AnnotationType::Error,
162-
Level::Warning => AnnotationType::Warning,
163-
Level::Note => AnnotationType::Note,
164-
Level::Help => AnnotationType::Help,
165-
// FIXME(#59346): Not sure how to map these two levels
166-
Level::Cancelled | Level::FailureNote => AnnotationType::Error,
167-
}
66+
/// Maps `Diagnostic::Level` to `snippet::AnnotationType`
67+
fn annotation_type_for_level(level: Level) -> AnnotationType {
68+
match level {
69+
Level::Bug | Level::Fatal | Level::Error => AnnotationType::Error,
70+
Level::Warning => AnnotationType::Warning,
71+
Level::Note => AnnotationType::Note,
72+
Level::Help => AnnotationType::Help,
73+
// FIXME(#59346): Not sure how to map these two levels
74+
Level::Cancelled | Level::FailureNote => AnnotationType::Error,
16875
}
16976
}
17077

@@ -191,25 +98,87 @@ impl AnnotateSnippetEmitterWriter {
19198
message: String,
19299
code: &Option<DiagnosticId>,
193100
msp: &MultiSpan,
194-
children: &[SubDiagnostic],
195-
suggestions: &[CodeSuggestion],
101+
_children: &[SubDiagnostic],
102+
_suggestions: &[CodeSuggestion],
196103
) {
197-
let converter = DiagnosticConverter {
198-
source_map: self.source_map.clone(),
199-
level: *level,
200-
message,
201-
code: code.clone(),
202-
msp: msp.clone(),
203-
children,
204-
suggestions,
205-
};
206-
if let Some(snippet) = converter.to_annotation_snippet() {
207-
let dl = DisplayList::from(snippet);
208-
let dlf = DisplayListFormatter::new(true, self.ui_testing);
104+
if let Some(source_map) = &self.source_map {
105+
// Make sure our primary file comes first
106+
let primary_lo = if let Some(ref primary_span) = msp.primary_span().as_ref() {
107+
if primary_span.is_dummy() {
108+
// FIXME(#59346): Not sure when this is the case and what
109+
// should be done if it happens
110+
return;
111+
} else {
112+
source_map.lookup_char_pos(primary_span.lo())
113+
}
114+
} else {
115+
// FIXME(#59346): Not sure when this is the case and what
116+
// should be done if it happens
117+
return;
118+
};
119+
let mut annotated_files =
120+
FileWithAnnotatedLines::collect_annotations(msp, &self.source_map);
121+
if let Ok(pos) =
122+
annotated_files.binary_search_by(|x| x.file.name.cmp(&primary_lo.file.name))
123+
{
124+
annotated_files.swap(0, pos);
125+
}
126+
// owned: line source, line index, annotations
127+
type Owned = (String, usize, Vec<crate::snippet::Annotation>);
128+
let origin = primary_lo.file.name.to_string();
129+
let annotated_files: Vec<Owned> = annotated_files
130+
.into_iter()
131+
.flat_map(|annotated_file| {
132+
let file = annotated_file.file;
133+
annotated_file
134+
.lines
135+
.into_iter()
136+
.map(|line| {
137+
(source_string(file.clone(), &line), line.line_index, line.annotations)
138+
})
139+
.collect::<Vec<Owned>>()
140+
})
141+
.collect();
142+
let snippet = Snippet {
143+
title: Some(Annotation {
144+
label: Some(&message),
145+
id: code.as_ref().map(|c| match c {
146+
DiagnosticId::Error(val) | DiagnosticId::Lint(val) => val.as_str(),
147+
}),
148+
annotation_type: annotation_type_for_level(*level),
149+
}),
150+
footer: vec![],
151+
opt: FormatOptions { color: true, anonymized_line_numbers: self.ui_testing },
152+
slices: annotated_files
153+
.iter()
154+
.map(|(source, line_index, annotations)| {
155+
Slice {
156+
source,
157+
line_start: *line_index,
158+
origin: Some(&origin),
159+
// FIXME(#59346): Not really sure when `fold` should be true or false
160+
fold: false,
161+
annotations: annotations
162+
.into_iter()
163+
.map(|annotation| SourceAnnotation {
164+
range: (annotation.start_col, annotation.end_col),
165+
label: annotation
166+
.label
167+
.as_ref()
168+
.map(|s| s.as_str())
169+
.unwrap_or_default(),
170+
annotation_type: annotation_type_for_level(*level),
171+
})
172+
.collect(),
173+
}
174+
})
175+
.collect(),
176+
};
209177
// FIXME(#59346): Figure out if we can _always_ print to stderr or not.
210178
// `emitter.rs` has the `Destination` enum that lists various possible output
211179
// destinations.
212-
eprintln!("{}", dlf.format(&dl));
213-
};
180+
eprintln!("{}", DisplayList::from(snippet))
181+
}
182+
// FIXME(#59346): Is it ok to return None if there's no source_map?
214183
}
215184
}

Diff for: src/test/ui/annotate-snippet/auxiliary/multispan.rs

+37
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
// force-host
2+
// no-prefer-dynamic
3+
4+
#![crate_type = "proc-macro"]
5+
#![feature(proc_macro_diagnostic, proc_macro_span, proc_macro_def_site)]
6+
7+
extern crate proc_macro;
8+
9+
use proc_macro::{TokenStream, TokenTree, Span, Diagnostic};
10+
11+
fn parse(input: TokenStream) -> Result<(), Diagnostic> {
12+
let mut hi_spans = vec![];
13+
for tree in input {
14+
if let TokenTree::Ident(ref ident) = tree {
15+
if ident.to_string() == "hi" {
16+
hi_spans.push(ident.span());
17+
}
18+
}
19+
}
20+
21+
if !hi_spans.is_empty() {
22+
return Err(Span::def_site()
23+
.error("hello to you, too!")
24+
.span_note(hi_spans, "found these 'hi's"));
25+
}
26+
27+
Ok(())
28+
}
29+
30+
#[proc_macro]
31+
pub fn hello(input: TokenStream) -> TokenStream {
32+
if let Err(diag) = parse(input) {
33+
diag.emit();
34+
}
35+
36+
TokenStream::new()
37+
}

Diff for: src/test/ui/annotate-snippet/missing-type.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error[E0412]: cannot find type `Iter` in this scope
2-
--> $DIR/missing-type.rs:4:11
2+
--> $DIR/missing-type.rs:4:12
33
|
44
LL | let x: Iter;
55
| ^^^^ not found in this scope

Diff for: src/test/ui/annotate-snippet/multispan.rs

+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// aux-build:multispan.rs
2+
// compile-flags: --error-format human-annotate-rs
3+
4+
#![feature(proc_macro_hygiene)]
5+
6+
extern crate multispan;
7+
8+
use multispan::hello;
9+
10+
fn main() {
11+
// This one emits no error.
12+
hello!();
13+
14+
// Exactly one 'hi'.
15+
hello!(hi); //~ ERROR hello to you, too!
16+
17+
// Now two, back to back.
18+
hello!(hi hi); //~ ERROR hello to you, too!
19+
20+
// Now three, back to back.
21+
hello!(hi hi hi); //~ ERROR hello to you, too!
22+
23+
// Now several, with spacing.
24+
hello!(hi hey hi yo hi beep beep hi hi); //~ ERROR hello to you, too!
25+
hello!(hi there, hi how are you? hi... hi.); //~ ERROR hello to you, too!
26+
hello!(whoah. hi di hi di ho); //~ ERROR hello to you, too!
27+
hello!(hi good hi and good bye); //~ ERROR hello to you, too!
28+
}

0 commit comments

Comments
 (0)