Skip to content

enable a way to elide the message "header" #167

Open
@BurntSushi

Description

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.

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions