Repository: rust-lang/annotate-snippets-rs (rust)

Issue:
Origin line number is not correct when using a slice with `fold: true`
Here is a test case demonstrating the issue:

```rs
#[test]
fn test_origin_line_numbers_with_fold() {
    let snippets = Snippet {
        title: Some(snippet::Annotation {
            id: None,
            label: Some("oops"),
            annotation_type: snippet::AnnotationType::Error,
        }),
        footer: vec![],
        slices: vec![snippet::Slice {
            source: "First line\r\n\r\n\r\nSecond oops line",
            line_start: 1,
            origin: Some("<current file>"),
            annotations: vec![
                snippet::SourceAnnotation {
                    range: (23, 27),
                    label: "oops",
                    annotation_type: snippet::AnnotationType::Error,
                },
                snippet::SourceAnnotation {
                    range: (0, 5),
                    label: "First",
                    annotation_type: snippet::AnnotationType::Info,
                },
            ],
            fold: true,
        }],
        opt: Default::default(),
    };
    let expected = r#"error: oops
 --> <current file>:4:8
  |
1 | First line
  | ----- info: First
...
4 | Second oops line
  |        ^^^^ oops
  |"#;

    assert_eq!(DisplayList::from(snippets).to_string(), expected);
}
```

`--> <current file>:2:8` is printed instead of `--> <current file>:4:8`.

Pull request:
Show correct line numbers when fold ist set to true, fixes #52
This pr changes the `format_header` function to use the line number that is already stored in `DisplayLine` instead of (wrongly) recomputing it.
Fixes #52 

Patch:
diff --git a/src/display_list/from_snippet.rs b/src/display_list/from_snippet.rs
index faf48f2..83e51f5 100644
--- a/src/display_list/from_snippet.rs
+++ b/src/display_list/from_snippet.rs
@@ -111,10 +111,9 @@ fn format_slice(
 ) -> Vec<DisplayLine<'_>> {
     let main_range = slice.annotations.get(0).map(|x| x.range.0);
     let origin = slice.origin;
-    let line_start = slice.line_start;
     let need_empty_header = origin.is_some() || is_first;
     let mut body = format_body(slice, need_empty_header, has_footer, margin);
-    let header = format_header(origin, main_range, line_start, &body, is_first);
+    let header = format_header(origin, main_range, &body, is_first);
     let mut result = vec![];
 
     if let Some(header) = header {
@@ -133,7 +132,6 @@ fn zip_opt<A, B>(a: Option<A>, b: Option<B>) -> Option<(A, B)> {
 fn format_header<'a>(
     origin: Option<&'a str>,
     main_range: Option<usize>,
-    mut row: usize,
     body: &[DisplayLine<'_>],
     is_first: bool,
 ) -> Option<DisplayLine<'a>> {
@@ -145,24 +143,26 @@ fn format_header<'a>(
 
     if let Some((main_range, path)) = zip_opt(main_range, origin) {
         let mut col = 1;
+        let mut line_offset = 1;
 
         for item in body {
             if let DisplayLine::Source {
                 line: DisplaySourceLine::Content { range, .. },
+                lineno,
                 ..
             } = item
             {
                 if main_range >= range.0 && main_range <= range.1 {
                     col = main_range - range.0 + 1;
+                    line_offset = lineno.unwrap_or(1);
                     break;
                 }
-                row += 1;
             }
         }
 
         return Some(DisplayLine::Raw(DisplayRawLine::Origin {
             path,
-            pos: Some((row, col)),
+            pos: Some((line_offset, col)),
             header_type: display_header,
         }));
     }
@@ -307,7 +307,7 @@ fn format_body(
         let char_widths = line
             .chars()
             .map(|c| unicode_width::UnicodeWidthChar::width(c).unwrap_or(0))
-            .chain(std::iter::once(1)) // treat the end of line as signle-width
+            .chain(std::iter::once(1)) // treat the end of line as single-width
             .collect::<Vec<_>>();
         body.push(DisplayLine::Source {
             lineno: Some(current_line),


Test patch:
diff --git a/tests/fixtures/no-color/issue_52.toml b/tests/fixtures/no-color/issue_52.toml
new file mode 100644
index 0000000..8d54613
--- /dev/null
+++ b/tests/fixtures/no-color/issue_52.toml
@@ -0,0 +1,16 @@
+[title]
+annotation_type = "Error"
+
+[[slices]]
+source = """
+
+
+invalid syntax
+"""
+line_start = 1
+origin = "path/to/error.rs"
+fold = true
+[[slices.annotations]]
+label = "error here"
+annotation_type = "Warning"
+range = [2,16]
diff --git a/tests/fixtures/no-color/issue_52.txt b/tests/fixtures/no-color/issue_52.txt
new file mode 100644
index 0000000..b1c6bf2
--- /dev/null
+++ b/tests/fixtures/no-color/issue_52.txt
@@ -0,0 +1,7 @@
+error
+ --> path/to/error.rs:3:1
+  |
+...
+3 | invalid syntax
+  | -------------- error here
+  |
\ No newline at end of file