diff options
Diffstat (limited to 'third_party/rust/codespan-reporting/tests/term.rs')
-rw-r--r-- | third_party/rust/codespan-reporting/tests/term.rs | 1053 |
1 files changed, 1053 insertions, 0 deletions
diff --git a/third_party/rust/codespan-reporting/tests/term.rs b/third_party/rust/codespan-reporting/tests/term.rs new file mode 100644 index 0000000000..035db9b459 --- /dev/null +++ b/third_party/rust/codespan-reporting/tests/term.rs @@ -0,0 +1,1053 @@ +use codespan_reporting::diagnostic::{Diagnostic, Label}; +use codespan_reporting::files::{SimpleFile, SimpleFiles}; +use codespan_reporting::term::{termcolor::Color, Chars, Config, DisplayStyle, Styles}; + +mod support; + +use self::support::TestData; + +lazy_static::lazy_static! { + static ref TEST_CONFIG: Config = Config { + // Always use blue so tests are consistent across platforms + styles: Styles::with_blue(Color::Blue), + ..Config::default() + }; +} + +macro_rules! test_emit { + (rich_color) => { + #[test] + fn rich_color() { + let config = Config { + display_style: DisplayStyle::Rich, + ..TEST_CONFIG.clone() + }; + + insta::assert_snapshot!(TEST_DATA.emit_color(&config)); + } + }; + (medium_color) => { + #[test] + fn medium_color() { + let config = Config { + display_style: DisplayStyle::Medium, + ..TEST_CONFIG.clone() + }; + + insta::assert_snapshot!(TEST_DATA.emit_color(&config)); + } + }; + (short_color) => { + #[test] + fn short_color() { + let config = Config { + display_style: DisplayStyle::Short, + ..TEST_CONFIG.clone() + }; + + insta::assert_snapshot!(TEST_DATA.emit_color(&config)); + } + }; + (rich_no_color) => { + #[test] + fn rich_no_color() { + let config = Config { + display_style: DisplayStyle::Rich, + ..TEST_CONFIG.clone() + }; + + insta::assert_snapshot!(TEST_DATA.emit_no_color(&config)); + } + }; + (medium_no_color) => { + #[test] + fn medium_no_color() { + let config = Config { + display_style: DisplayStyle::Medium, + ..TEST_CONFIG.clone() + }; + + insta::assert_snapshot!(TEST_DATA.emit_no_color(&config)); + } + }; + (short_no_color) => { + #[test] + fn short_no_color() { + let config = Config { + display_style: DisplayStyle::Short, + ..TEST_CONFIG.clone() + }; + + insta::assert_snapshot!(TEST_DATA.emit_no_color(&config)); + } + }; + (rich_ascii_no_color) => { + #[test] + fn rich_ascii_no_color() { + let config = Config { + display_style: DisplayStyle::Rich, + chars: Chars::ascii(), + ..TEST_CONFIG.clone() + }; + + insta::assert_snapshot!(TEST_DATA.emit_no_color(&config)); + } + }; +} + +mod empty { + use super::*; + + lazy_static::lazy_static! { + static ref TEST_DATA: TestData<'static, SimpleFiles<&'static str, &'static str>> = { + let files = SimpleFiles::new(); + + let diagnostics = vec![ + Diagnostic::bug(), + Diagnostic::error(), + Diagnostic::warning(), + Diagnostic::note(), + Diagnostic::help(), + Diagnostic::bug(), + ]; + + TestData { files, diagnostics } + }; + } + + test_emit!(rich_color); + test_emit!(medium_color); + test_emit!(short_color); + test_emit!(rich_no_color); + test_emit!(medium_no_color); + test_emit!(short_no_color); + test_emit!(rich_ascii_no_color); +} + +/// Based on: +/// - https://github.com/rust-lang/rust/blob/c20d7eecbc0928b57da8fe30b2ef8528e2bdd5be/src/test/ui/codemap_tests/one_line.stderr +mod same_line { + use super::*; + + lazy_static::lazy_static! { + static ref TEST_DATA: TestData<'static, SimpleFiles<&'static str, String>> = { + let mut files = SimpleFiles::new(); + + let file_id1 = files.add( + "one_line.rs", + unindent::unindent(r#" + fn main() { + let mut v = vec![Some("foo"), Some("bar")]; + v.push(v.pop().unwrap()); + } + "#), + ); + + let diagnostics = vec![ + Diagnostic::error() + .with_code("E0499") + .with_message("cannot borrow `v` as mutable more than once at a time") + .with_labels(vec![ + Label::primary(file_id1, 71..72) + .with_message("second mutable borrow occurs here"), + Label::secondary(file_id1, 64..65) + .with_message("first borrow later used by call"), + Label::secondary(file_id1, 66..70) + .with_message("first mutable borrow occurs here"), + ]), + Diagnostic::error() + .with_message("aborting due to previous error") + .with_notes(vec![ + "For more information about this error, try `rustc --explain E0499`.".to_owned(), + ]), + ]; + + TestData { files, diagnostics } + }; + } + + test_emit!(rich_color); + test_emit!(medium_color); + test_emit!(short_color); + test_emit!(rich_no_color); + test_emit!(medium_no_color); + test_emit!(short_no_color); + test_emit!(rich_ascii_no_color); +} + +/// Based on: +/// - https://github.com/rust-lang/rust/blob/c20d7eecbc0928b57da8fe30b2ef8528e2bdd5be/src/test/ui/nested_impl_trait.stderr +/// - https://github.com/rust-lang/rust/blob/c20d7eecbc0928b57da8fe30b2ef8528e2bdd5be/src/test/ui/typeck/typeck_type_placeholder_item.stderr +/// - https://github.com/rust-lang/rust/blob/c20d7eecbc0928b57da8fe30b2ef8528e2bdd5be/src/test/ui/no_send_res_ports.stderr +mod overlapping { + use super::*; + + lazy_static::lazy_static! { + static ref TEST_DATA: TestData<'static, SimpleFiles<&'static str, String>> = { + let mut files = SimpleFiles::new(); + + let file_id1 = files.add( + "nested_impl_trait.rs", + unindent::unindent(r#" + use std::fmt::Debug; + + fn fine(x: impl Into<u32>) -> impl Into<u32> { x } + + fn bad_in_ret_position(x: impl Into<u32>) -> impl Into<impl Debug> { x } + "#), + ); + let file_id2 = files.add( + "typeck_type_placeholder_item.rs", + unindent::unindent(r#" + fn fn_test1() -> _ { 5 } + fn fn_test2(x: i32) -> (_, _) { (x, x) } + "#), + ); + let file_id3 = files.add( + "libstd/thread/mod.rs", + unindent::unindent(r#" + #[stable(feature = "rust1", since = "1.0.0")] + pub fn spawn<F, T>(self, f: F) -> io::Result<JoinHandle<T>> + where + F: FnOnce() -> T, + F: Send + 'static, + T: Send + 'static, + { + unsafe { self.spawn_unchecked(f) } + } + "#), + ); + let file_id4 = files.add( + "no_send_res_ports.rs", + unindent::unindent(r#" + use std::thread; + use std::rc::Rc; + + #[derive(Debug)] + struct Port<T>(Rc<T>); + + fn main() { + #[derive(Debug)] + struct Foo { + _x: Port<()>, + } + + impl Drop for Foo { + fn drop(&mut self) {} + } + + fn foo(x: Port<()>) -> Foo { + Foo { + _x: x + } + } + + let x = foo(Port(Rc::new(()))); + + thread::spawn(move|| { + let y = x; + println!("{:?}", y); + }); + } + "#), + ); + + let diagnostics = vec![ + Diagnostic::error() + .with_code("E0666") + .with_message("nested `impl Trait` is not allowed") + .with_labels(vec![ + Label::primary(file_id1, 129..139) + .with_message("nested `impl Trait` here"), + Label::secondary(file_id1, 119..140) + .with_message("outer `impl Trait`"), + ]), + Diagnostic::error() + .with_code("E0121") + .with_message("the type placeholder `_` is not allowed within types on item signatures") + .with_labels(vec![ + Label::primary(file_id2, 17..18) + .with_message("not allowed in type signatures"), + Label::secondary(file_id2, 17..18) + .with_message("help: replace with the correct return type: `i32`"), + ]), + Diagnostic::error() + .with_code("E0121") + .with_message("the type placeholder `_` is not allowed within types on item signatures") + .with_labels(vec![ + Label::primary(file_id2, 49..50) + .with_message("not allowed in type signatures"), + Label::primary(file_id2, 52..53) + .with_message("not allowed in type signatures"), + Label::secondary(file_id2, 48..54) + .with_message("help: replace with the correct return type: `(i32, i32)`"), + ]), + Diagnostic::error() + .with_code("E0277") + .with_message("`std::rc::Rc<()>` cannot be sent between threads safely") + .with_labels(vec![ + Label::primary(file_id4, 339..352) + .with_message("`std::rc::Rc<()>` cannot be sent between threads safely"), + Label::secondary(file_id4, 353..416) + .with_message("within this `[closure@no_send_res_ports.rs:29:19: 33:6 x:main::Foo]`"), + Label::secondary(file_id3, 141..145) + .with_message("required by this bound in `std::thread::spawn`"), + ]) + .with_notes(vec![ + "help: within `[closure@no_send_res_ports.rs:29:19: 33:6 x:main::Foo]`, the trait `std::marker::Send` is not implemented for `std::rc::Rc<()>`".to_owned(), + "note: required because it appears within the type `Port<()>`".to_owned(), + "note: required because it appears within the type `main::Foo`".to_owned(), + "note: required because it appears within the type `[closure@no_send_res_ports.rs:29:19: 33:6 x:main::Foo]`".to_owned(), + ]), + Diagnostic::error() + .with_message("aborting due 5 previous errors") + .with_notes(vec![ + "Some errors have detailed explanations: E0121, E0277, E0666.".to_owned(), + "For more information about an error, try `rustc --explain E0121`.".to_owned(), + ]), + ]; + + TestData { files, diagnostics } + }; + } + + test_emit!(rich_color); + test_emit!(medium_color); + test_emit!(short_color); + test_emit!(rich_no_color); + test_emit!(medium_no_color); + test_emit!(short_no_color); + test_emit!(rich_ascii_no_color); +} + +mod message { + use super::*; + + lazy_static::lazy_static! { + static ref TEST_DATA: TestData<'static, SimpleFiles<&'static str, &'static str>> = { + let files = SimpleFiles::new(); + + let diagnostics = vec![ + Diagnostic::error().with_message("a message"), + Diagnostic::warning().with_message("a message"), + Diagnostic::note().with_message("a message"), + Diagnostic::help().with_message("a message"), + ]; + + TestData { files, diagnostics } + }; + } + + test_emit!(rich_color); + test_emit!(medium_color); + test_emit!(short_color); + test_emit!(rich_no_color); + test_emit!(medium_no_color); + test_emit!(short_no_color); + test_emit!(rich_ascii_no_color); +} + +mod message_and_notes { + use super::*; + + lazy_static::lazy_static! { + static ref TEST_DATA: TestData<'static, SimpleFiles<&'static str, &'static str>> = { + let files = SimpleFiles::new(); + + let diagnostics = vec![ + Diagnostic::error().with_message("a message").with_notes(vec!["a note".to_owned()]), + Diagnostic::warning().with_message("a message").with_notes(vec!["a note".to_owned()]), + Diagnostic::note().with_message("a message").with_notes(vec!["a note".to_owned()]), + Diagnostic::help().with_message("a message").with_notes(vec!["a note".to_owned()]), + ]; + + TestData { files, diagnostics } + }; + } + + test_emit!(rich_color); + test_emit!(medium_color); + test_emit!(short_color); + test_emit!(rich_no_color); + test_emit!(medium_no_color); + test_emit!(short_no_color); + test_emit!(rich_ascii_no_color); +} + +mod message_errorcode { + use super::*; + + lazy_static::lazy_static! { + static ref TEST_DATA: TestData<'static, SimpleFiles<&'static str, &'static str>> = { + let files = SimpleFiles::new(); + + let diagnostics = vec![ + Diagnostic::error().with_message("a message").with_code("E0001"), + Diagnostic::warning().with_message("a message").with_code("W001"), + Diagnostic::note().with_message("a message").with_code("N0815"), + Diagnostic::help().with_message("a message").with_code("H4711"), + Diagnostic::error().with_message("where did my errorcode go?").with_code(""), + Diagnostic::warning().with_message("where did my errorcode go?").with_code(""), + Diagnostic::note().with_message("where did my errorcode go?").with_code(""), + Diagnostic::help().with_message("where did my errorcode go?").with_code(""), + ]; + + TestData { files, diagnostics } + }; + } + + test_emit!(rich_no_color); + test_emit!(short_no_color); + test_emit!(rich_ascii_no_color); +} + +mod empty_ranges { + use super::*; + + lazy_static::lazy_static! { + static ref TEST_DATA: TestData<'static, SimpleFile<&'static str, &'static str>> = { + let file = SimpleFile::new("hello", "Hello world!\nBye world!\n "); + let eof = file.source().len(); + + let diagnostics = vec![ + Diagnostic::note() + .with_message("middle") + .with_labels(vec![Label::primary((), 6..6).with_message("middle")]), + Diagnostic::note() + .with_message("end of line") + .with_labels(vec![Label::primary((), 12..12).with_message("end of line")]), + Diagnostic::note() + .with_message("end of line") + .with_labels(vec![Label::primary((), 23..23).with_message("end of line")]), + Diagnostic::note() + .with_message("end of file") + .with_labels(vec![Label::primary((), eof..eof).with_message("end of file")]), + ]; + + TestData { files: file, diagnostics } + }; + } + + test_emit!(rich_color); + test_emit!(medium_color); + test_emit!(short_color); + test_emit!(rich_no_color); + test_emit!(medium_no_color); + test_emit!(short_no_color); + test_emit!(rich_ascii_no_color); +} + +mod same_ranges { + use super::*; + + lazy_static::lazy_static! { + static ref TEST_DATA: TestData<'static, SimpleFile<&'static str, &'static str>> = { + let file = SimpleFile::new("same_range", "::S { }"); + + let diagnostics = vec![ + Diagnostic::error() + .with_message("Unexpected token") + .with_labels(vec![ + Label::primary((), 4..4).with_message("Unexpected '{'"), + Label::secondary((), 4..4).with_message("Expected '('"), + ]), + ]; + + TestData { files: file, diagnostics } + }; + } + + test_emit!(rich_color); + test_emit!(medium_color); + test_emit!(short_color); + test_emit!(rich_no_color); + test_emit!(medium_no_color); + test_emit!(short_no_color); + test_emit!(rich_ascii_no_color); +} + +mod multifile { + use super::*; + + lazy_static::lazy_static! { + static ref TEST_DATA: TestData<'static, SimpleFiles<&'static str, String>> = { + let mut files = SimpleFiles::new(); + + let file_id1 = files.add( + "Data/Nat.fun", + unindent::unindent( + " + module Data.Nat where + + data Nat : Type where + zero : Nat + succ : Nat → Nat + + {-# BUILTIN NATRAL Nat #-} + + infixl 6 _+_ _-_ + + _+_ : Nat → Nat → Nat + zero + n₂ = n₂ + succ n₁ + n₂ = succ (n₁ + n₂) + + _-_ : Nat → Nat → Nat + n₁ - zero = n₁ + zero - succ n₂ = zero + succ n₁ - succ n₂ = n₁ - n₂ + ", + ), + ); + + let file_id2 = files.add( + "Test.fun", + unindent::unindent( + r#" + module Test where + + _ : Nat + _ = 123 + "hello" + "#, + ), + ); + + let diagnostics = vec![ + // Unknown builtin error + Diagnostic::error() + .with_message("unknown builtin: `NATRAL`") + .with_labels(vec![Label::primary(file_id1, 96..102).with_message("unknown builtin")]) + .with_notes(vec![ + "there is a builtin with a similar name: `NATURAL`".to_owned(), + ]), + // Unused parameter warning + Diagnostic::warning() + .with_message("unused parameter pattern: `n₂`") + .with_labels(vec![Label::primary(file_id1, 285..289).with_message("unused parameter")]) + .with_notes(vec!["consider using a wildcard pattern: `_`".to_owned()]), + // Unexpected type error + Diagnostic::error() + .with_message("unexpected type in application of `_+_`") + .with_code("E0001") + .with_labels(vec![ + Label::primary(file_id2, 37..44).with_message("expected `Nat`, found `String`"), + Label::secondary(file_id1, 130..155).with_message("based on the definition of `_+_`"), + ]) + .with_notes(vec![unindent::unindent( + " + expected type `Nat` + found type `String` + ", + )]), + ]; + + TestData { files, diagnostics } + }; + } + + test_emit!(rich_color); + test_emit!(medium_color); + test_emit!(short_color); + test_emit!(rich_no_color); + test_emit!(medium_no_color); + test_emit!(short_no_color); + test_emit!(rich_ascii_no_color); +} + +mod fizz_buzz { + use super::*; + + lazy_static::lazy_static! { + static ref TEST_DATA: TestData<'static, SimpleFiles<&'static str, String>> = { + let mut files = SimpleFiles::new(); + + let file_id = files.add( + "FizzBuzz.fun", + unindent::unindent( + r#" + module FizzBuzz where + + fizz₁ : Nat → String + fizz₁ num = case (mod num 5) (mod num 3) of + 0 0 => "FizzBuzz" + 0 _ => "Fizz" + _ 0 => "Buzz" + _ _ => num + + fizz₂ : Nat → String + fizz₂ num = + case (mod num 5) (mod num 3) of + 0 0 => "FizzBuzz" + 0 _ => "Fizz" + _ 0 => "Buzz" + _ _ => num + "#, + ), + ); + + let diagnostics = vec![ + // Incompatible match clause error + Diagnostic::error() + .with_message("`case` clauses have incompatible types") + .with_code("E0308") + .with_labels(vec![ + Label::primary(file_id, 163..166).with_message("expected `String`, found `Nat`"), + Label::secondary(file_id, 62..166).with_message("`case` clauses have incompatible types"), + Label::secondary(file_id, 41..47).with_message("expected type `String` found here"), + ]) + .with_notes(vec![unindent::unindent( + " + expected type `String` + found type `Nat` + ", + )]), + // Incompatible match clause error + Diagnostic::error() + .with_message("`case` clauses have incompatible types") + .with_code("E0308") + .with_labels(vec![ + Label::primary(file_id, 328..331).with_message("expected `String`, found `Nat`"), + Label::secondary(file_id, 211..331).with_message("`case` clauses have incompatible types"), + Label::secondary(file_id, 258..268).with_message("this is found to be of type `String`"), + Label::secondary(file_id, 284..290).with_message("this is found to be of type `String`"), + Label::secondary(file_id, 306..312).with_message("this is found to be of type `String`"), + Label::secondary(file_id, 186..192).with_message("expected type `String` found here"), + ]) + .with_notes(vec![unindent::unindent( + " + expected type `String` + found type `Nat` + ", + )]), + ]; + + TestData { files, diagnostics } + }; + } + + test_emit!(rich_color); + test_emit!(medium_color); + test_emit!(short_color); + test_emit!(rich_no_color); + test_emit!(medium_no_color); + test_emit!(short_no_color); + test_emit!(rich_ascii_no_color); +} + +mod multiline_overlapping { + use super::*; + + lazy_static::lazy_static! { + static ref TEST_DATA: TestData<'static, SimpleFile<&'static str, String>> = { + let file = SimpleFile::new( + "codespan/src/file.rs", + [ + " match line_index.compare(self.last_line_index()) {", + " Ordering::Less => Ok(self.line_starts()[line_index.to_usize()]),", + " Ordering::Equal => Ok(self.source_span().end()),", + " Ordering::Greater => LineIndexOutOfBoundsError {", + " given: line_index,", + " max: self.last_line_index(),", + " },", + " }", + ].join("\n"), + ); + + let diagnostics = vec![ + Diagnostic::error() + .with_message("match arms have incompatible types") + .with_code("E0308") + .with_labels(vec![ + // this secondary label is before the primary label to test the locus calculation (see issue #259) + Label::secondary((), 89..134).with_message("this is found to be of type `Result<ByteIndex, LineIndexOutOfBoundsError>`"), + Label::primary((), 230..351).with_message("expected enum `Result`, found struct `LineIndexOutOfBoundsError`"), + Label::secondary((), 8..362).with_message("`match` arms have incompatible types"), + Label::secondary((), 167..195).with_message("this is found to be of type `Result<ByteIndex, LineIndexOutOfBoundsError>`"), + ]) + .with_notes(vec![unindent::unindent( + " + expected type `Result<ByteIndex, LineIndexOutOfBoundsError>` + found type `LineIndexOutOfBoundsError` + ", + )]), + ]; + + TestData { files: file, diagnostics } + }; + } + + test_emit!(rich_color); + test_emit!(medium_color); + test_emit!(short_color); + test_emit!(rich_no_color); + test_emit!(medium_no_color); + test_emit!(short_no_color); + test_emit!(rich_ascii_no_color); +} + +mod tabbed { + use super::*; + + lazy_static::lazy_static! { + static ref TEST_DATA: TestData<'static, SimpleFiles<&'static str, String>> = { + let mut files = SimpleFiles::new(); + + let file_id = files.add( + "tabbed", + [ + "Entity:", + "\tArmament:", + "\t\tWeapon: DogJaw", + "\t\tReloadingCondition:\tattack-cooldown", + "\tFoo: Bar", + ] + .join("\n"), + ); + + let diagnostics = vec![ + Diagnostic::warning() + .with_message("unknown weapon `DogJaw`") + .with_labels(vec![Label::primary(file_id, 29..35).with_message("the weapon")]), + Diagnostic::warning() + .with_message("unknown condition `attack-cooldown`") + .with_labels(vec![Label::primary(file_id, 58..73).with_message("the condition")]), + Diagnostic::warning() + .with_message("unknown field `Foo`") + .with_labels(vec![Label::primary(file_id, 75..78).with_message("the field")]), + ]; + + TestData { files, diagnostics } + }; + } + + #[test] + fn tab_width_default_no_color() { + let config = TEST_CONFIG.clone(); + + insta::assert_snapshot!(TEST_DATA.emit_no_color(&config)); + } + + #[test] + fn tab_width_3_no_color() { + let config = Config { + tab_width: 3, + ..TEST_CONFIG.clone() + }; + + insta::assert_snapshot!(TEST_DATA.emit_no_color(&config)); + } + + #[test] + fn tab_width_6_no_color() { + let config = Config { + tab_width: 6, + ..TEST_CONFIG.clone() + }; + + insta::assert_snapshot!(TEST_DATA.emit_no_color(&config)); + } +} + +mod tab_columns { + use super::*; + + lazy_static::lazy_static! { + static ref TEST_DATA: TestData<'static, SimpleFiles<&'static str, String>> = { + let mut files = SimpleFiles::new(); + + let source = [ + "\thello", + "∙\thello", + "∙∙\thello", + "∙∙∙\thello", + "∙∙∙∙\thello", + "∙∙∙∙∙\thello", + "∙∙∙∙∙∙\thello", + ].join("\n"); + let hello_ranges = source + .match_indices("hello") + .map(|(start, hello)| start..(start+hello.len())) + .collect::<Vec<_>>(); + + let file_id = files.add("tab_columns", source); + + let diagnostics = vec![ + Diagnostic::warning() + .with_message("tab test") + .with_labels( + hello_ranges + .into_iter() + .map(|range| Label::primary(file_id, range)) + .collect(), + ), + ]; + + TestData { files, diagnostics } + }; + } + + #[test] + fn tab_width_default_no_color() { + let config = TEST_CONFIG.clone(); + + insta::assert_snapshot!(TEST_DATA.emit_no_color(&config)); + } + + #[test] + fn tab_width_2_no_color() { + let config = Config { + tab_width: 2, + ..TEST_CONFIG.clone() + }; + + insta::assert_snapshot!(TEST_DATA.emit_no_color(&config)); + } + + #[test] + fn tab_width_3_no_color() { + let config = Config { + tab_width: 3, + ..TEST_CONFIG.clone() + }; + + insta::assert_snapshot!(TEST_DATA.emit_no_color(&config)); + } + + #[test] + fn tab_width_6_no_color() { + let config = Config { + tab_width: 6, + ..TEST_CONFIG.clone() + }; + + insta::assert_snapshot!(TEST_DATA.emit_no_color(&config)); + } +} + +/// Based on: +/// - https://github.com/TheSamsa/rust/blob/75cf41afb468152611212271bae026948cd3ba46/src/test/ui/codemap_tests/unicode.stderr +mod unicode { + use super::*; + + lazy_static::lazy_static! { + static ref TEST_DATA: TestData<'static, SimpleFile<&'static str, String>> = { + let prefix = r#"extern "#; + let abi = r#""路濫狼á́́""#; + let suffix = r#" fn foo() {}"#; + + let file = SimpleFile::new( + "unicode.rs", + format!("{}{}{}", prefix, abi, suffix), + ); + + let diagnostics = vec![ + Diagnostic::error() + .with_code("E0703") + .with_message("invalid ABI: found `路濫狼á́́`") + .with_labels(vec![ + Label::primary((), prefix.len()..(prefix.len() + abi.len())) + .with_message("invalid ABI"), + ]) + .with_notes(vec![unindent::unindent( + " + valid ABIs: + - aapcs + - amdgpu-kernel + - C + - cdecl + - efiapi + - fastcall + - msp430-interrupt + - platform-intrinsic + - ptx-kernel + - Rust + - rust-call + - rust-intrinsic + - stdcall + - system + - sysv64 + - thiscall + - unadjusted + - vectorcall + - win64 + - x86-interrupt + ", + )]), + Diagnostic::error() + .with_message("aborting due to previous error") + .with_notes(vec![ + "For more information about this error, try `rustc --explain E0703`.".to_owned(), + ]), + ]; + + TestData { files: file, diagnostics } + }; + } + + test_emit!(rich_no_color); + test_emit!(medium_no_color); + test_emit!(short_no_color); +} + +mod unicode_spans { + use super::*; + + lazy_static::lazy_static! { + static ref TEST_DATA: TestData<'static, SimpleFile<&'static str, String>> = { + let moon_phases = format!("{}", r#"🐄🌑🐄🌒🐄🌓🐄🌔🐄🌕🐄🌖🐄🌗🐄🌘🐄"#); + let invalid_start = 1; + let invalid_end = "🐄".len() - 1; + assert_eq!(moon_phases.is_char_boundary(invalid_start), false); + assert_eq!(moon_phases.is_char_boundary(invalid_end), false); + assert_eq!("🐄".len(), 4); + let file = SimpleFile::new( + "moon_jump.rs", + moon_phases, + ); + let diagnostics = vec![ + Diagnostic::error() + .with_code("E01") + .with_message("cow may not jump during new moon.") + .with_labels(vec![ + Label::primary((), invalid_start..invalid_end) + .with_message("Invalid jump"), + ]), + Diagnostic::note() + .with_message("invalid unicode range") + .with_labels(vec![ + Label::secondary((), invalid_start.."🐄".len()) + .with_message("Cow range does not start at boundary."), + ]), + Diagnostic::note() + .with_message("invalid unicode range") + .with_labels(vec![ + Label::secondary((), "🐄🌑".len().."🐄🌑🐄".len() - 1) + .with_message("Cow range does not end at boundary."), + ]), + Diagnostic::note() + .with_message("invalid unicode range") + .with_labels(vec![ + Label::secondary((), invalid_start.."🐄🌑🐄".len() - 1) + .with_message("Cow does not start or end at boundary."), + ]), + ]; + TestData{files: file, diagnostics } + }; + } + + test_emit!(rich_no_color); + test_emit!(medium_no_color); + test_emit!(short_no_color); +} + +mod position_indicator { + use super::*; + + lazy_static::lazy_static! { + static ref TEST_DATA: TestData<'static, SimpleFile<&'static str, String>> = { + let file = SimpleFile::new( + "tests/main.js", + [ + "\"use strict\";", + "let zero=0;", + "function foo() {", + " \"use strict\";", + " one=1;", + "}", + ].join("\n"), + ); + let diagnostics = vec![ + Diagnostic::warning() + .with_code("ParserWarning") + .with_message("The strict mode declaration in the body of function `foo` is redundant, as the outer scope is already in strict mode") + .with_labels(vec![ + Label::primary((), 45..57) + .with_message("This strict mode declaration is redundant"), + Label::secondary((), 0..12) + .with_message("Strict mode is first declared here"), + ]), + ]; + TestData{files: file, diagnostics } + }; + } + + test_emit!(rich_no_color); + test_emit!(medium_no_color); + test_emit!(short_no_color); + test_emit!(rich_ascii_no_color); +} + +mod multiline_omit { + use super::*; + + lazy_static::lazy_static! { + static ref TEST_CONFIG: Config = Config { + styles: Styles::with_blue(Color::Blue), + start_context_lines: 2, + end_context_lines: 1, + ..Config::default() + }; + + static ref TEST_DATA: TestData<'static, SimpleFiles<&'static str, String>> = { + let mut files = SimpleFiles::new(); + + let file_id1 = files.add( + "empty_if_comments.lua", + [ + "elseif 3 then", // primary label starts here + "", // context line + "", + "", + "", + "", + "", + "", + "", // context line + "else", // primary label ends here + ] + .join("\n"), + ); + + let file_id2 = files.add( + "src/lib.rs", + [ + "fn main() {", + " 1", // primary label starts here + " + 1", // context line + " + 1", // skip + " + 1", // skip + " + 1", // skip + " +1", // secondary label here + " + 1", // this single line will not be skipped; the previously filtered out label must be retrieved + " + 1", // context line + " + 1", // primary label ends here + "}", + ] + .join("\n"), + ); + + let diagnostics = vec![ + Diagnostic::error() + .with_message("empty elseif block") + .with_code("empty_if") + .with_labels(vec![ + Label::primary(file_id1, 0..23), + Label::secondary(file_id1, 15..21).with_message("content should be in here"), + ]), + Diagnostic::error() + .with_message("mismatched types") + .with_code("E0308") + .with_labels(vec![ + Label::primary(file_id2, 17..80).with_message("expected (), found integer"), + Label::secondary(file_id2, 55..55).with_message("missing whitespace"), + ]) + .with_notes(vec![ + "note:\texpected type `()`\n\tfound type `{integer}`".to_owned() + ]), + ]; + + TestData { files, diagnostics } + }; + } + + test_emit!(rich_no_color); +} |