mirror of
https://github.com/astral-sh/ruff.git
synced 2025-11-02 04:48:07 +00:00
## Summary This PR is a spin-off from https://github.com/astral-sh/ruff/pull/19415. It enables replacing the severity and lint name in a ty-style diagnostic: ``` error[unused-import]: `os` imported but unused ``` with the noqa code and optional fix availability icon for a Ruff diagnostic: ``` F401 [*] `os` imported but unused F821 Undefined name `a` ``` or nothing at all for a Ruff syntax error: ``` SyntaxError: Expected one or more symbol names after import ``` Ruff adds the `SyntaxError` prefix to these messages manually. Initially (d912458), I just passed a `hide_severity` flag through a bunch of calls to get it into `annotate-snippets`, but after looking at it again today, I think reusing the `None` severity/level gave a nicer result. As I note in a lengthy code comment, I think all of this code should be temporary and reverted when Ruff gets real severities, so hopefully it's okay if it feels a little hacky. I think the main visible downside of this approach is that we can't style the asterisk in the fix availabilty icon in cyan, as in Ruff's current output. It's part of the message in this PR and any styling gets overwritten in `annotate-snippets`. <img width="400" height="342" alt="image" src="https://github.com/user-attachments/assets/57542ec9-a81c-4a01-91c7-bd6d7ec99f99" /> Hmm, I guess reusing `Level::None` also means the `F401` isn't red anymore. Maybe my initial approach was better after all. In any case, the rest of the PR should be basically the same, it just depends how we want to toggle the severity. ## Test Plan New `ruff_db` tests. These snapshots should be compared to the two tests just above them (`hide_severity_output` vs `output` and `hide_severity_syntax_errors` against `syntax_errors`).
90 lines
2.7 KiB
Rust
90 lines
2.7 KiB
Rust
use std::io::Write;
|
|
|
|
use ruff_db::diagnostic::Diagnostic;
|
|
use ruff_source_file::LineColumn;
|
|
|
|
use crate::fs::relativize_path;
|
|
use crate::message::{Emitter, EmitterContext};
|
|
|
|
/// Generate error workflow command in GitHub Actions format.
|
|
/// See: [GitHub documentation](https://docs.github.com/en/actions/reference/workflow-commands-for-github-actions#setting-an-error-message)
|
|
#[derive(Default)]
|
|
pub struct GithubEmitter;
|
|
|
|
impl Emitter for GithubEmitter {
|
|
fn emit(
|
|
&mut self,
|
|
writer: &mut dyn Write,
|
|
diagnostics: &[Diagnostic],
|
|
context: &EmitterContext,
|
|
) -> anyhow::Result<()> {
|
|
for diagnostic in diagnostics {
|
|
let source_location = diagnostic.expect_ruff_start_location();
|
|
let filename = diagnostic.expect_ruff_filename();
|
|
let location = if context.is_notebook(&filename) {
|
|
// We can't give a reasonable location for the structured formats,
|
|
// so we show one that's clearly a fallback
|
|
LineColumn::default()
|
|
} else {
|
|
source_location
|
|
};
|
|
|
|
let end_location = diagnostic.expect_ruff_end_location();
|
|
|
|
write!(
|
|
writer,
|
|
"::error title=Ruff ({code}),file={file},line={row},col={column},endLine={end_row},endColumn={end_column}::",
|
|
code = diagnostic.secondary_code_or_id(),
|
|
file = filename,
|
|
row = source_location.line,
|
|
column = source_location.column,
|
|
end_row = end_location.line,
|
|
end_column = end_location.column,
|
|
)?;
|
|
|
|
write!(
|
|
writer,
|
|
"{path}:{row}:{column}:",
|
|
path = relativize_path(&filename),
|
|
row = location.line,
|
|
column = location.column,
|
|
)?;
|
|
|
|
if let Some(code) = diagnostic.secondary_code() {
|
|
write!(writer, " {code}")?;
|
|
} else {
|
|
write!(writer, " {id}:", id = diagnostic.id())?;
|
|
}
|
|
|
|
writeln!(writer, " {}", diagnostic.body())?;
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use insta::assert_snapshot;
|
|
|
|
use crate::message::GithubEmitter;
|
|
use crate::message::tests::{
|
|
capture_emitter_output, create_diagnostics, create_syntax_error_diagnostics,
|
|
};
|
|
|
|
#[test]
|
|
fn output() {
|
|
let mut emitter = GithubEmitter;
|
|
let content = capture_emitter_output(&mut emitter, &create_diagnostics());
|
|
|
|
assert_snapshot!(content);
|
|
}
|
|
|
|
#[test]
|
|
fn syntax_errors() {
|
|
let mut emitter = GithubEmitter;
|
|
let content = capture_emitter_output(&mut emitter, &create_syntax_error_diagnostics());
|
|
|
|
assert_snapshot!(content);
|
|
}
|
|
}
|