From df076b2d5e21bd62263efbb1a6345492a7e302ca Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Wed, 5 Jun 2019 21:13:56 +0200 Subject: librustc_errors: Rename AnnotateRs -> AnnotateSnippet The proper name of the library is `annotate-snippet`, not `annotate-rs`, this commit should get rid of any confusing `AnnotateRs` names. 1. Renames `annotate_rs_emitter.rs` to `annotate_snippet_emitter_writer.rs` so that the difference between the `Emitter` trait and the implementers is more clear. 2. Renames `AnnotateRsEmitterWriter` to `AnnotateSnippetEmitterWriter` 3. Renames `HumanReadableErrorType::AnnotateRs` to `HumanReadableErrorType::AnnotateSnippet` --- src/librustc_errors/annotate_rs_emitter.rs | 212 --------------------- .../annotate_snippet_emitter_writer.rs | 212 +++++++++++++++++++++ src/librustc_errors/emitter.rs | 4 +- src/librustc_errors/lib.rs | 2 +- 4 files changed, 215 insertions(+), 215 deletions(-) delete mode 100644 src/librustc_errors/annotate_rs_emitter.rs create mode 100644 src/librustc_errors/annotate_snippet_emitter_writer.rs (limited to 'src/librustc_errors') diff --git a/src/librustc_errors/annotate_rs_emitter.rs b/src/librustc_errors/annotate_rs_emitter.rs deleted file mode 100644 index de42389de74..00000000000 --- a/src/librustc_errors/annotate_rs_emitter.rs +++ /dev/null @@ -1,212 +0,0 @@ -/// Emit diagnostics using the `annotate-snippets` library -/// -/// This is the equivalent of `./emitter.rs` but making use of the -/// [`annotate-snippets`][annotate_snippets] library instead of building the output ourselves. -/// -/// [annotate_snippets]: https://docs.rs/crate/annotate-snippets/ - -use syntax_pos::{SourceFile, MultiSpan, Loc}; -use crate::{ - Level, CodeSuggestion, DiagnosticBuilder, Emitter, - SourceMapperDyn, SubDiagnostic, DiagnosticId -}; -use crate::emitter::FileWithAnnotatedLines; -use rustc_data_structures::sync::Lrc; -use crate::snippet::Line; -use annotate_snippets::snippet::*; -use annotate_snippets::display_list::DisplayList; -use annotate_snippets::formatter::DisplayListFormatter; - - -/// Generates diagnostics using annotate-rs -pub struct AnnotateRsEmitterWriter { - source_map: Option>, - /// If true, hides the longer explanation text - short_message: bool, - /// If true, will normalize line numbers with LL to prevent noise in UI test diffs. - ui_testing: bool, -} - -impl Emitter for AnnotateRsEmitterWriter { - /// The entry point for the diagnostics generation - fn emit_diagnostic(&mut self, db: &DiagnosticBuilder<'_>) { - let primary_span = db.span.clone(); - let children = db.children.clone(); - // FIXME(#59346): Collect suggestions (see emitter.rs) - let suggestions: &[_] = &[]; - - // FIXME(#59346): Add `fix_multispans_in_std_macros` function from emitter.rs - - self.emit_messages_default(&db.level, - db.message(), - &db.code, - &primary_span, - &children, - &suggestions); - } - - fn should_show_explain(&self) -> bool { - !self.short_message - } -} - -/// Collects all the data needed to generate the data structures needed for the -/// `annotate-snippets` library. -struct DiagnosticConverter<'a> { - source_map: Option>, - level: Level, - message: String, - code: Option, - msp: MultiSpan, - #[allow(dead_code)] - children: &'a [SubDiagnostic], - #[allow(dead_code)] - suggestions: &'a [CodeSuggestion] -} - -impl<'a> DiagnosticConverter<'a> { - /// Turns rustc Diagnostic information into a `annotate_snippets::snippet::Snippet`. - fn to_annotation_snippet(&self) -> Option { - 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: 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, - primary_lo: Loc - ) -> Vec { - // FIXME(#59346): 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::>() - }).collect::>() - } - - /// 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, - 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::PhaseFatal | 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 - } - } -} - -impl AnnotateRsEmitterWriter { - pub fn new( - source_map: Option>, - short_message: bool - ) -> Self { - Self { - source_map, - short_message, - ui_testing: false, - } - } - - /// Allows to modify `Self` to enable or disable the `ui_testing` flag. - /// - /// If this is set to true, line numbers will be normalized as `LL` in the output. - // FIXME(#59346): This method is used via the public interface, but setting the `ui_testing` - // flag currently does not anonymize line numbers. We would have to add the `maybe_anonymized` - // method from `emitter.rs` and implement rust-lang/annotate-snippets-rs#2 in order to - // anonymize line numbers. - pub fn ui_testing(mut self, ui_testing: bool) -> Self { - self.ui_testing = ui_testing; - self - } - - fn emit_messages_default( - &mut self, - level: &Level, - message: String, - code: &Option, - msp: &MultiSpan, - children: &[SubDiagnostic], - suggestions: &[CodeSuggestion] - ) { - let converter = DiagnosticConverter { - source_map: self.source_map.clone(), - level: level.clone(), - message: message.clone(), - 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); - // 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)); - }; - } -} diff --git a/src/librustc_errors/annotate_snippet_emitter_writer.rs b/src/librustc_errors/annotate_snippet_emitter_writer.rs new file mode 100644 index 00000000000..9f9c7588d97 --- /dev/null +++ b/src/librustc_errors/annotate_snippet_emitter_writer.rs @@ -0,0 +1,212 @@ +//! Emit diagnostics using the `annotate-snippets` library +//! +//! This is the equivalent of `./emitter.rs` but making use of the +//! [`annotate-snippets`][annotate_snippets] library instead of building the output ourselves. +//! +//! [annotate_snippets]: https://docs.rs/crate/annotate-snippets/ + +use syntax_pos::{SourceFile, MultiSpan, Loc}; +use crate::{ + Level, CodeSuggestion, DiagnosticBuilder, Emitter, + SourceMapperDyn, SubDiagnostic, DiagnosticId +}; +use crate::emitter::FileWithAnnotatedLines; +use rustc_data_structures::sync::Lrc; +use crate::snippet::Line; +use annotate_snippets::snippet::*; +use annotate_snippets::display_list::DisplayList; +use annotate_snippets::formatter::DisplayListFormatter; + + +/// Generates diagnostics using annotate-snippet +pub struct AnnotateSnippetEmitterWriter { + source_map: Option>, + /// If true, hides the longer explanation text + short_message: bool, + /// If true, will normalize line numbers with LL to prevent noise in UI test diffs. + ui_testing: bool, +} + +impl Emitter for AnnotateSnippetEmitterWriter { + /// The entry point for the diagnostics generation + fn emit_diagnostic(&mut self, db: &DiagnosticBuilder<'_>) { + let primary_span = db.span.clone(); + let children = db.children.clone(); + // FIXME(#59346): Collect suggestions (see emitter.rs) + let suggestions: &[_] = &[]; + + // FIXME(#59346): Add `fix_multispans_in_std_macros` function from emitter.rs + + self.emit_messages_default(&db.level, + db.message(), + &db.code, + &primary_span, + &children, + &suggestions); + } + + fn should_show_explain(&self) -> bool { + !self.short_message + } +} + +/// Collects all the data needed to generate the data structures needed for the +/// `annotate-snippets` library. +struct DiagnosticConverter<'a> { + source_map: Option>, + level: Level, + message: String, + code: Option, + msp: MultiSpan, + #[allow(dead_code)] + children: &'a [SubDiagnostic], + #[allow(dead_code)] + suggestions: &'a [CodeSuggestion] +} + +impl<'a> DiagnosticConverter<'a> { + /// Turns rustc Diagnostic information into a `annotate_snippets::snippet::Snippet`. + fn to_annotation_snippet(&self) -> Option { + 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: 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, + primary_lo: Loc + ) -> Vec { + // FIXME(#59346): 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::>() + }).collect::>() + } + + /// 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, + 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::PhaseFatal | 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 + } + } +} + +impl AnnotateSnippetEmitterWriter { + pub fn new( + source_map: Option>, + short_message: bool + ) -> Self { + Self { + source_map, + short_message, + ui_testing: false, + } + } + + /// Allows to modify `Self` to enable or disable the `ui_testing` flag. + /// + /// If this is set to true, line numbers will be normalized as `LL` in the output. + // FIXME(#59346): This method is used via the public interface, but setting the `ui_testing` + // flag currently does not anonymize line numbers. We would have to add the `maybe_anonymized` + // method from `emitter.rs` and implement rust-lang/annotate-snippets-rs#2 in order to + // anonymize line numbers. + pub fn ui_testing(mut self, ui_testing: bool) -> Self { + self.ui_testing = ui_testing; + self + } + + fn emit_messages_default( + &mut self, + level: &Level, + message: String, + code: &Option, + msp: &MultiSpan, + children: &[SubDiagnostic], + suggestions: &[CodeSuggestion] + ) { + let converter = DiagnosticConverter { + source_map: self.source_map.clone(), + level: level.clone(), + message: message.clone(), + 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); + // 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)); + }; + } +} diff --git a/src/librustc_errors/emitter.rs b/src/librustc_errors/emitter.rs index fcc0358ea7c..3bf477efe35 100644 --- a/src/librustc_errors/emitter.rs +++ b/src/librustc_errors/emitter.rs @@ -24,7 +24,7 @@ use termcolor::{WriteColor, Color, Buffer}; #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub enum HumanReadableErrorType { Default(ColorConfig), - AnnotateRs(ColorConfig), + AnnotateSnippet(ColorConfig), Short(ColorConfig), } @@ -34,7 +34,7 @@ impl HumanReadableErrorType { match self { HumanReadableErrorType::Default(cc) => (false, cc), HumanReadableErrorType::Short(cc) => (true, cc), - HumanReadableErrorType::AnnotateRs(cc) => (false, cc), + HumanReadableErrorType::AnnotateSnippet(cc) => (false, cc), } } pub fn new_emitter( diff --git a/src/librustc_errors/lib.rs b/src/librustc_errors/lib.rs index 7bc7d0ddaf2..1831d58e736 100644 --- a/src/librustc_errors/lib.rs +++ b/src/librustc_errors/lib.rs @@ -33,7 +33,7 @@ use termcolor::{ColorSpec, Color}; mod diagnostic; mod diagnostic_builder; pub mod emitter; -pub mod annotate_rs_emitter; +pub mod annotate_snippet_emitter_writer; mod snippet; pub mod registry; mod styled_buffer; -- cgit 1.4.1-3-g733a5