Update annotate-snippets-rs to 0.8.0
This commit is contained in:
parent
7b805396bf
commit
e9c78db086
4 changed files with 92 additions and 128 deletions
12
Cargo.lock
12
Cargo.lock
|
@ -48,6 +48,12 @@ dependencies = [
|
|||
"ansi_term",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "annotate-snippets"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d78ea013094e5ea606b1c05fe35f1dd7ea1eb1ea259908d040b25bd5ec677ee5"
|
||||
|
||||
[[package]]
|
||||
name = "ansi_term"
|
||||
version = "0.11.0"
|
||||
|
@ -3277,7 +3283,7 @@ version = "654.0.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "908e1ea187c6bb368af4ba6db980001e920515e67371ddc4086e749baabe6080"
|
||||
dependencies = [
|
||||
"annotate-snippets",
|
||||
"annotate-snippets 0.6.1",
|
||||
"atty",
|
||||
"log",
|
||||
"rustc-ap-rustc_data_structures",
|
||||
|
@ -3761,7 +3767,7 @@ version = "0.0.0"
|
|||
name = "rustc_errors"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"annotate-snippets",
|
||||
"annotate-snippets 0.8.0",
|
||||
"atty",
|
||||
"log",
|
||||
"rustc_data_structures",
|
||||
|
@ -4408,7 +4414,7 @@ dependencies = [
|
|||
name = "rustfmt-nightly"
|
||||
version = "1.4.14"
|
||||
dependencies = [
|
||||
"annotate-snippets",
|
||||
"annotate-snippets 0.6.1",
|
||||
"bytecount",
|
||||
"cargo_metadata 0.8.0",
|
||||
"derive-new",
|
||||
|
|
|
@ -17,7 +17,7 @@ rustc_data_structures = { path = "../librustc_data_structures" }
|
|||
unicode-width = "0.1.4"
|
||||
atty = "0.2"
|
||||
termcolor = "1.0"
|
||||
annotate-snippets = "0.6.1"
|
||||
annotate-snippets = "0.8.0"
|
||||
termize = "0.1.1"
|
||||
|
||||
[target.'cfg(windows)'.dependencies]
|
||||
|
|
|
@ -8,12 +8,11 @@
|
|||
use crate::emitter::FileWithAnnotatedLines;
|
||||
use crate::snippet::Line;
|
||||
use crate::{CodeSuggestion, Diagnostic, DiagnosticId, Emitter, Level, SubDiagnostic};
|
||||
use annotate_snippets::display_list::DisplayList;
|
||||
use annotate_snippets::formatter::DisplayListFormatter;
|
||||
use annotate_snippets::display_list::{DisplayList, FormatOptions};
|
||||
use annotate_snippets::snippet::*;
|
||||
use rustc_data_structures::sync::Lrc;
|
||||
use rustc_span::source_map::SourceMap;
|
||||
use rustc_span::{Loc, MultiSpan, SourceFile};
|
||||
use rustc_span::{MultiSpan, SourceFile};
|
||||
|
||||
/// Generates diagnostics using annotate-snippet
|
||||
pub struct AnnotateSnippetEmitterWriter {
|
||||
|
@ -59,112 +58,20 @@ impl Emitter for AnnotateSnippetEmitterWriter {
|
|||
}
|
||||
}
|
||||
|
||||
/// Collects all the data needed to generate the data structures needed for the
|
||||
/// `annotate-snippets` library.
|
||||
struct DiagnosticConverter<'a> {
|
||||
source_map: Option<Lrc<SourceMap>>,
|
||||
level: Level,
|
||||
message: String,
|
||||
code: Option<DiagnosticId>,
|
||||
msp: MultiSpan,
|
||||
#[allow(dead_code)]
|
||||
children: &'a [SubDiagnostic],
|
||||
#[allow(dead_code)]
|
||||
suggestions: &'a [CodeSuggestion],
|
||||
/// Provides the source string for the given `line` of `file`
|
||||
fn source_string(file: Lrc<SourceFile>, line: &Line) -> String {
|
||||
file.get_line(line.line_index - 1).map(|a| a.to_string()).unwrap_or_default()
|
||||
}
|
||||
|
||||
impl<'a> DiagnosticConverter<'a> {
|
||||
/// Turns rustc Diagnostic information into a `annotate_snippets::snippet::Snippet`.
|
||||
fn to_annotation_snippet(&self) -> Option<Snippet> {
|
||||
if let Some(source_map) = &self.source_map {
|
||||
// Make sure our primary file comes first
|
||||
let primary_lo = if let Some(ref primary_span) = self.msp.primary_span().as_ref() {
|
||||
source_map.lookup_char_pos(primary_span.lo())
|
||||
} else {
|
||||
// FIXME(#59346): Not sure when this is the case and what
|
||||
// should be done if it happens
|
||||
return None;
|
||||
};
|
||||
let annotated_files =
|
||||
FileWithAnnotatedLines::collect_annotations(&self.msp, &self.source_map);
|
||||
let slices = self.slices_for_files(annotated_files, primary_lo);
|
||||
|
||||
Some(Snippet {
|
||||
title: Some(Annotation {
|
||||
label: Some(self.message.to_string()),
|
||||
id: self.code.clone().map(|c| match c {
|
||||
DiagnosticId::Error(val) | DiagnosticId::Lint(val) => val,
|
||||
}),
|
||||
annotation_type: Self::annotation_type_for_level(self.level),
|
||||
}),
|
||||
footer: vec![],
|
||||
slices,
|
||||
})
|
||||
} else {
|
||||
// FIXME(#59346): Is it ok to return None if there's no source_map?
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
fn slices_for_files(
|
||||
&self,
|
||||
annotated_files: Vec<FileWithAnnotatedLines>,
|
||||
primary_lo: Loc,
|
||||
) -> Vec<Slice> {
|
||||
// FIXME(#64205): Provide a test case where `annotated_files` is > 1
|
||||
annotated_files
|
||||
.iter()
|
||||
.flat_map(|annotated_file| {
|
||||
annotated_file
|
||||
.lines
|
||||
.iter()
|
||||
.map(|line| {
|
||||
let line_source = Self::source_string(annotated_file.file.clone(), &line);
|
||||
Slice {
|
||||
source: line_source,
|
||||
line_start: line.line_index,
|
||||
origin: Some(primary_lo.file.name.to_string()),
|
||||
// FIXME(#59346): Not really sure when `fold` should be true or false
|
||||
fold: false,
|
||||
annotations: line
|
||||
.annotations
|
||||
.iter()
|
||||
.map(|a| self.annotation_to_source_annotation(a.clone()))
|
||||
.collect(),
|
||||
}
|
||||
})
|
||||
.collect::<Vec<Slice>>()
|
||||
})
|
||||
.collect::<Vec<Slice>>()
|
||||
}
|
||||
|
||||
/// Turns a `crate::snippet::Annotation` into a `SourceAnnotation`
|
||||
fn annotation_to_source_annotation(
|
||||
&self,
|
||||
annotation: crate::snippet::Annotation,
|
||||
) -> SourceAnnotation {
|
||||
SourceAnnotation {
|
||||
range: (annotation.start_col, annotation.end_col),
|
||||
label: annotation.label.unwrap_or("".to_string()),
|
||||
annotation_type: Self::annotation_type_for_level(self.level),
|
||||
}
|
||||
}
|
||||
|
||||
/// Provides the source string for the given `line` of `file`
|
||||
fn source_string(file: Lrc<SourceFile>, line: &Line) -> String {
|
||||
file.get_line(line.line_index - 1).map(|a| a.to_string()).unwrap_or(String::new())
|
||||
}
|
||||
|
||||
/// Maps `Diagnostic::Level` to `snippet::AnnotationType`
|
||||
fn annotation_type_for_level(level: Level) -> AnnotationType {
|
||||
match level {
|
||||
Level::Bug | Level::Fatal | Level::Error => AnnotationType::Error,
|
||||
Level::Warning => AnnotationType::Warning,
|
||||
Level::Note => AnnotationType::Note,
|
||||
Level::Help => AnnotationType::Help,
|
||||
// FIXME(#59346): Not sure how to map these two levels
|
||||
Level::Cancelled | Level::FailureNote => AnnotationType::Error,
|
||||
}
|
||||
/// Maps `Diagnostic::Level` to `snippet::AnnotationType`
|
||||
fn annotation_type_for_level(level: Level) -> AnnotationType {
|
||||
match level {
|
||||
Level::Bug | Level::Fatal | Level::Error => AnnotationType::Error,
|
||||
Level::Warning => AnnotationType::Warning,
|
||||
Level::Note => AnnotationType::Note,
|
||||
Level::Help => AnnotationType::Help,
|
||||
// FIXME(#59346): Not sure how to map these two levels
|
||||
Level::Cancelled | Level::FailureNote => AnnotationType::Error,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -191,25 +98,76 @@ impl AnnotateSnippetEmitterWriter {
|
|||
message: String,
|
||||
code: &Option<DiagnosticId>,
|
||||
msp: &MultiSpan,
|
||||
children: &[SubDiagnostic],
|
||||
suggestions: &[CodeSuggestion],
|
||||
_children: &[SubDiagnostic],
|
||||
_suggestions: &[CodeSuggestion],
|
||||
) {
|
||||
let converter = DiagnosticConverter {
|
||||
source_map: self.source_map.clone(),
|
||||
level: *level,
|
||||
message,
|
||||
code: code.clone(),
|
||||
msp: msp.clone(),
|
||||
children,
|
||||
suggestions,
|
||||
};
|
||||
if let Some(snippet) = converter.to_annotation_snippet() {
|
||||
let dl = DisplayList::from(snippet);
|
||||
let dlf = DisplayListFormatter::new(true, self.ui_testing);
|
||||
if let Some(source_map) = &self.source_map {
|
||||
// Make sure our primary file comes first
|
||||
let primary_lo = if let Some(ref primary_span) = msp.primary_span().as_ref() {
|
||||
source_map.lookup_char_pos(primary_span.lo())
|
||||
} else {
|
||||
// FIXME(#59346): Not sure when this is the case and what
|
||||
// should be done if it happens
|
||||
return;
|
||||
};
|
||||
let annotated_files =
|
||||
FileWithAnnotatedLines::collect_annotations(msp, &self.source_map);
|
||||
// owned: line source, line index, annotations
|
||||
type Owned = (String, usize, Vec<crate::snippet::Annotation>);
|
||||
let origin = primary_lo.file.name.to_string();
|
||||
let annotated_files: Vec<Owned> = annotated_files
|
||||
.into_iter()
|
||||
.flat_map(|annotated_file| {
|
||||
let file = annotated_file.file;
|
||||
annotated_file
|
||||
.lines
|
||||
.into_iter()
|
||||
.map(|line| {
|
||||
(source_string(file.clone(), &line), line.line_index, line.annotations)
|
||||
})
|
||||
.collect::<Vec<Owned>>()
|
||||
})
|
||||
.collect();
|
||||
let snippet = Snippet {
|
||||
title: Some(Annotation {
|
||||
label: Some(&message),
|
||||
id: code.as_ref().map(|c| match c {
|
||||
DiagnosticId::Error(val) | DiagnosticId::Lint(val) => val.as_str(),
|
||||
}),
|
||||
annotation_type: annotation_type_for_level(*level),
|
||||
}),
|
||||
footer: vec![],
|
||||
opt: FormatOptions { color: true, anonymized_line_numbers: self.ui_testing },
|
||||
slices: annotated_files
|
||||
.iter()
|
||||
.map(|(source, line_index, annotations)| {
|
||||
Slice {
|
||||
source,
|
||||
line_start: *line_index,
|
||||
origin: Some(&origin),
|
||||
// FIXME(#59346): Not really sure when `fold` should be true or false
|
||||
fold: false,
|
||||
annotations: annotations
|
||||
.into_iter()
|
||||
.map(|annotation| SourceAnnotation {
|
||||
range: (annotation.start_col, annotation.end_col),
|
||||
label: annotation
|
||||
.label
|
||||
.as_ref()
|
||||
.map(|s| s.as_str())
|
||||
.unwrap_or_default(),
|
||||
annotation_type: annotation_type_for_level(*level),
|
||||
})
|
||||
.collect(),
|
||||
}
|
||||
})
|
||||
.collect(),
|
||||
};
|
||||
// FIXME(#59346): Figure out if we can _always_ print to stderr or not.
|
||||
// `emitter.rs` has the `Destination` enum that lists various possible output
|
||||
// destinations.
|
||||
eprintln!("{}", dlf.format(&dl));
|
||||
};
|
||||
eprintln!("{}", DisplayList::from(snippet))
|
||||
}
|
||||
// FIXME(#59346): Is it ok to return None if there's no source_map?
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
error[E0412]: cannot find type `Iter` in this scope
|
||||
--> $DIR/missing-type.rs:4:11
|
||||
--> $DIR/missing-type.rs:4:12
|
||||
|
|
||||
LL | let x: Iter;
|
||||
| ^^^^ not found in this scope
|
||||
|
|
Loading…
Add table
Reference in a new issue