summaryrefslogtreecommitdiffstats
path: root/third_party/rust/codespan-reporting/tests/term.rs
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 09:22:09 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 09:22:09 +0000
commit43a97878ce14b72f0981164f87f2e35e14151312 (patch)
tree620249daf56c0258faa40cbdcf9cfba06de2a846 /third_party/rust/codespan-reporting/tests/term.rs
parentInitial commit. (diff)
downloadfirefox-43a97878ce14b72f0981164f87f2e35e14151312.tar.xz
firefox-43a97878ce14b72f0981164f87f2e35e14151312.zip
Adding upstream version 110.0.1.upstream/110.0.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'third_party/rust/codespan-reporting/tests/term.rs')
-rw-r--r--third_party/rust/codespan-reporting/tests/term.rs1053
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);
+}