annotate-snippets-rs icon indicating copy to clipboard operation
annotate-snippets-rs copied to clipboard

enable a way to elide the message "header"

Open BurntSushi opened this issue 10 months ago • 2 comments

I'm somewhat new to this crate, so apologies for any category or vernacular errors that I make.

I'm looking at migrating ruff from annotate-snippets 0.9 to annotate-snippets 0.11. But I'm hitting an issue where we would like to use our own headers for snippets. This worked in 0.9, but I can't find a way to replicate it in 0.11. To make this concrete, consider this program using 0.9:

use annotate_snippets::{
    display_list::{DisplayList, FormatOptions},
    snippet::{Annotation, AnnotationType, Slice, Snippet, SourceAnnotation},
};

fn main() {
    let snippet = Snippet {
        title: None,
        footer: vec![
            Annotation {
                id: None,
                label: Some(
                    "Replace with `None`; initialize within function",
                ),
                annotation_type: AnnotationType::Help,
            },
        ],
        slices: vec![
            Slice {
                source: "# Docstring followed by a newline\n\ndef foobar(foor, bar={}):    \n    \"\"\"\n    \"\"\"\n",
                line_start: 1,
                origin: None,
                annotations: vec![
                    SourceAnnotation {
                        range: (
                            56,
                            58,
                        ),
                        label: "B006",
                        annotation_type: AnnotationType::Error,
                    },
                ],
                fold: false,
            },
        ],
        opt: FormatOptions {
            color: false,
            anonymized_line_numbers: false,
            margin: None,
        },
    };
    println!("{message}", message = DisplayList::from(snippet));
}

It has this output:

  |
1 | # Docstring followed by a newline
2 |
3 | def foobar(foor, bar={}):
  |                      ^^ B006
4 |     """
5 |     """
  |
  = help: Replace with `None`; initialize within function

In ruff, this gets transformed slightly to include a header:

B006_1.py:3:22: B006 [*] Do not use mutable data structures for argument defaults
  |
1 | # Docstring followed by a newline
2 |
3 | def foobar(foor, bar={}):
  |                      ^^ B006
4 |     """
5 |     """
  |
  = help: Replace with `None`; initialize within function

Now consider this program, using 0.11, which tries to mimic the above program:

use annotate_snippets::{Level, Renderer, Snippet};

fn main() {
    let source = "# Docstring followed by a newline\n\ndef foobar(foor, bar={}):    \n    \"\"\"\n    \"\"\"\n";
    let src_annotation = Level::Error.span(56..58).label("B006");
    let snippet = Snippet::source(source)
        .line_start(1)
        .annotation(src_annotation)
        .fold(false);
    let footer =
        Level::Help.title("Replace with `None`; initialize within function");
    let message =
        Level::Error.title("<TITLE>").snippet(snippet).footer(footer);
    println!("{}", Renderer::plain().render(message));
}

It has this output:

error: <TITLE>
  |
1 | # Docstring followed by a newline
2 |
3 | def foobar(foor, bar={}):
  |                      ^^ B006
4 |     """
5 |     """
  |
  = help: Replace with `None`; initialize within function

Which is... very close to what we had before. But it now has an error: <TITLE> line that I don't think can be removed. At least, it seems to correspond to a requirement to create a message by providing a Level with a title.

Is this an intended change to the library that isn't meant to be configurable? If so, I think our options are to either go our own way or to explore changing the formatting of our own diagnostics (which we could do, but I definitely want to see if I can de-couple upgrading annotate-snippets from "let's reconsider our diagnostic formatting").

I do see some other issues and PRs seemingly related to this issue, but I wasn't 100% sure if this was a strict duplicate or not. So I wanted to put my use case in writing and see where that takes us.

BurntSushi avatar Dec 20 '24 15:12 BurntSushi