Repository: zkat/miette
Pull request #348 (2024-02-21 20:57:32)

fix(redundant-import): fix a warning and CI failure in nightly


Patch:
diff --git a/src/handlers/graphical.rs b/src/handlers/graphical.rs
index 3f74227..a4474f9 100644
--- a/src/handlers/graphical.rs
+++ b/src/handlers/graphical.rs
@@ -436,9 +436,25 @@ impl GraphicalReportHandler {
 
         let mut contexts = Vec::with_capacity(labels.len());
         for right in labels.iter().cloned() {
-            let right_conts = source
-                .read_span(right.inner(), self.context_lines, self.context_lines)
-                .map_err(|_| fmt::Error)?;
+            let right_conts =
+                match source.read_span(right.inner(), self.context_lines, self.context_lines) {
+                    Ok(cont) => cont,
+                    Err(err) => {
+                        writeln!(
+                            f,
+                            "  [{} `{}` (offset: {}, length: {}): {:?}]",
+                            "Failed to read contents for label".style(self.theme.styles.error),
+                            right
+                                .label()
+                                .unwrap_or("<none>")
+                                .style(self.theme.styles.link),
+                            right.offset().style(self.theme.styles.link),
+                            right.len().style(self.theme.styles.link),
+                            err.style(self.theme.styles.warning)
+                        )?;
+                        return Ok(());
+                    }
+                };
 
             if contexts.is_empty() {
                 contexts.push((right, right_conts));
diff --git a/src/source_impls.rs b/src/source_impls.rs
index e43a665..e362b4a 100644
--- a/src/source_impls.rs
+++ b/src/source_impls.rs
@@ -1,12 +1,7 @@
 /*!
 Default trait implementations for [`SourceCode`].
 */
-use std::{
-    borrow::{Cow, ToOwned},
-    collections::VecDeque,
-    fmt::Debug,
-    sync::Arc,
-};
+use std::{borrow::Cow, collections::VecDeque, fmt::Debug, sync::Arc};
 
 use crate::{MietteError, MietteSpanContents, SourceCode, SourceSpan, SpanContents};
 


Test patch:
diff --git a/tests/graphical.rs b/tests/graphical.rs
index b5fa4d8..4763117 100644
--- a/tests/graphical.rs
+++ b/tests/graphical.rs
@@ -1970,3 +1970,229 @@ fn non_adjacent_highlight() -> Result<(), MietteError> {
     assert_eq!(expected, &out);
     Ok(())
 }
+
+#[test]
+fn invalid_span_bad_offset() -> Result<(), MietteError> {
+    #[derive(Debug, Diagnostic, Error)]
+    #[error("oops!")]
+    #[diagnostic(code(oops::my::bad), help("help info"))]
+    struct MyBad {
+        #[source_code]
+        src: NamedSource<String>,
+        #[label = "1st"]
+        highlight1: SourceSpan,
+    }
+
+    let src = "blabla blibli".to_string();
+    let err = MyBad {
+        src: NamedSource::new("bad_file.rs", src),
+        highlight1: (50, 6).into(),
+    };
+    let out = fmt_report(err.into());
+    println!("Error: {}", out);
+    let expected = "oops::my::bad
+
+  × oops!
+  [Failed to read contents for label `1st` (offset: 50, length: 6): OutOfBounds]
+  help: help info
+";
+    assert_eq!(expected, &out);
+    Ok(())
+}
+
+#[test]
+fn invalid_span_bad_length() -> Result<(), MietteError> {
+    #[derive(Debug, Diagnostic, Error)]
+    #[error("oops!")]
+    #[diagnostic(code(oops::my::bad), help("help info"))]
+    struct MyBad {
+        #[source_code]
+        src: NamedSource<String>,
+        #[label = "1st"]
+        highlight1: SourceSpan,
+    }
+
+    let src = "blabla blibli".to_string();
+    let err = MyBad {
+        src: NamedSource::new("bad_file.rs", src),
+        highlight1: (0, 50).into(),
+    };
+    let out = fmt_report(err.into());
+    println!("Error: {}", out);
+    let expected = "oops::my::bad
+
+  × oops!
+  [Failed to read contents for label `1st` (offset: 0, length: 50): OutOfBounds]
+  help: help info
+";
+    assert_eq!(expected, &out);
+    Ok(())
+}
+
+#[test]
+fn invalid_span_no_label() -> Result<(), MietteError> {
+    #[derive(Debug, Diagnostic, Error)]
+    #[error("oops!")]
+    #[diagnostic(code(oops::my::bad), help("help info"))]
+    struct MyBad {
+        #[source_code]
+        src: NamedSource<String>,
+        #[label]
+        highlight1: SourceSpan,
+    }
+
+    let src = "blabla blibli".to_string();
+    let err = MyBad {
+        src: NamedSource::new("bad_file.rs", src),
+        highlight1: (50, 6).into(),
+    };
+    let out = fmt_report(err.into());
+    println!("Error: {}", out);
+    let expected = "oops::my::bad
+
+  × oops!
+  [Failed to read contents for label `<none>` (offset: 50, length: 6): OutOfBounds]
+  help: help info
+";
+    assert_eq!(expected, &out);
+    Ok(())
+}
+
+#[test]
+fn invalid_span_2nd_label() -> Result<(), MietteError> {
+    #[derive(Debug, Diagnostic, Error)]
+    #[error("oops!")]
+    #[diagnostic(code(oops::my::bad), help("help info"))]
+    struct MyBad {
+        #[source_code]
+        src: NamedSource<String>,
+        #[label("1st")]
+        highlight1: SourceSpan,
+        #[label("2nd")]
+        highlight2: SourceSpan,
+    }
+
+    let src = "blabla blibli".to_string();
+    let err = MyBad {
+        src: NamedSource::new("bad_file.rs", src),
+        highlight1: (0, 6).into(),
+        highlight2: (50, 6).into(),
+    };
+    let out = fmt_report(err.into());
+    println!("Error: {}", out);
+    let expected = "oops::my::bad
+
+  × oops!
+  [Failed to read contents for label `2nd` (offset: 50, length: 6): OutOfBounds]
+  help: help info
+";
+    assert_eq!(expected, &out);
+    Ok(())
+}
+
+#[test]
+fn invalid_span_inner() -> Result<(), MietteError> {
+    #[derive(Debug, Diagnostic, Error)]
+    #[error("oops inside!")]
+    #[diagnostic(code(oops::my::inner), help("help info"))]
+    struct MyInner {
+        #[source_code]
+        src: NamedSource<String>,
+        #[label("inner label")]
+        inner_label: SourceSpan,
+    }
+
+    #[derive(Debug, Diagnostic, Error)]
+    #[error("oops outside!")]
+    #[diagnostic(code(oops::my::outer), help("help info"))]
+    struct MyBad {
+        #[source_code]
+        src: NamedSource<String>,
+        #[label("outer label")]
+        outer_label: SourceSpan,
+        #[source]
+        inner: MyInner,
+    }
+
+    let src_outer = "outer source".to_string();
+    let src_inner = "inner source".to_string();
+    let err = MyBad {
+        src: NamedSource::new("bad_file.rs", src_outer),
+        outer_label: (0, 6).into(),
+        inner: MyInner {
+            src: NamedSource::new("bad_file2.rs", src_inner),
+            inner_label: (60, 6).into(),
+        },
+    };
+    let out = fmt_report(err.into());
+    println!("Error: {}", out);
+    let expected = "oops::my::outer
+
+  × oops outside!
+  ╰─▶ oops inside!
+   ╭─[bad_file.rs:1:1]
+ 1 │ outer source
+   · ───┬──
+   ·    ╰── outer label
+   ╰────
+  help: help info
+";
+    assert_eq!(expected, &out);
+    Ok(())
+}
+
+#[test]
+fn invalid_span_related() -> Result<(), MietteError> {
+    #[derive(Debug, Diagnostic, Error)]
+    #[error("oops inside!")]
+    #[diagnostic(code(oops::my::inner), help("help info"))]
+    struct MyRelated {
+        #[source_code]
+        src: NamedSource<String>,
+        #[label("inner label")]
+        inner_label: SourceSpan,
+    }
+
+    #[derive(Debug, Diagnostic, Error)]
+    #[error("oops outside!")]
+    #[diagnostic(code(oops::my::outer), help("help info"))]
+    struct MyBad {
+        #[source_code]
+        src: NamedSource<String>,
+        #[label("outer label")]
+        outer_label: SourceSpan,
+        #[related]
+        inner: Vec<MyRelated>,
+    }
+
+    let src_outer = "outer source".to_string();
+    let src_inner = "related source".to_string();
+    let err = MyBad {
+        src: NamedSource::new("bad_file.rs", src_outer),
+        outer_label: (0, 6).into(),
+        inner: vec![MyRelated {
+            src: NamedSource::new("bad_file2.rs", src_inner),
+            inner_label: (60, 6).into(),
+        }],
+    };
+    let out = fmt_report(err.into());
+    println!("Error: {}", out);
+    let expected = "oops::my::outer
+
+  × oops outside!
+   ╭─[bad_file.rs:1:1]
+ 1 │ outer source
+   · ───┬──
+   ·    ╰── outer label
+   ╰────
+  help: help info
+
+Error: oops::my::inner
+
+  × oops inside!
+  [Failed to read contents for label `inner label` (offset: 60, length: 6): OutOfBounds]
+  help: help info
+";
+    assert_eq!(expected, &out);
+    Ok(())
+}
diff --git a/tests/test_repr.rs b/tests/test_repr.rs
index 4978fe5..65ea6d5 100644
--- a/tests/test_repr.rs
+++ b/tests/test_repr.rs
@@ -2,7 +2,6 @@ mod drop;
 
 use self::drop::{DetectDrop, Flag};
 use miette::Report;
-use std::marker::Unpin;
 use std::mem;
 
 #[test]