mirror of
https://github.com/astral-sh/ruff.git
synced 2025-08-03 10:23:11 +00:00
red_knot: plumb through DiagnosticFormat
to the CLI
The CLI calls this `OutputFormat`, and so does the type where the CLI is defined. But it's called `DiagnosticFormat` in `ruff_db` to be consistent with `DisplayDiagnosticConfig`. Ref https://github.com/astral-sh/ruff/issues/15697#issuecomment-2706477278
This commit is contained in:
parent
eb6871d209
commit
2bcd2b4147
6 changed files with 104 additions and 1 deletions
|
@ -75,6 +75,10 @@ pub(crate) struct CheckCommand {
|
|||
#[clap(flatten)]
|
||||
pub(crate) rules: RulesArg,
|
||||
|
||||
/// The format to use for printing diagnostic messages.
|
||||
#[arg(long)]
|
||||
pub(crate) output_format: Option<OutputFormat>,
|
||||
|
||||
/// Use exit code 1 if there are any warning-level diagnostics.
|
||||
#[arg(long, conflicts_with = "exit_zero", default_missing_value = "true", num_args=0..1)]
|
||||
pub(crate) error_on_warning: Option<bool>,
|
||||
|
@ -117,6 +121,9 @@ impl CheckCommand {
|
|||
..EnvironmentOptions::default()
|
||||
}),
|
||||
terminal: Some(TerminalOptions {
|
||||
output_format: self
|
||||
.output_format
|
||||
.map(|output_format| RangedValue::cli(output_format.into())),
|
||||
error_on_warning: self.error_on_warning,
|
||||
}),
|
||||
rules,
|
||||
|
@ -211,3 +218,32 @@ impl clap::Args for RulesArg {
|
|||
Self::augment_args(cmd)
|
||||
}
|
||||
}
|
||||
|
||||
/// The diagnostic output format.
|
||||
#[derive(Copy, Clone, Hash, Debug, PartialEq, Eq, PartialOrd, Ord, Default, clap::ValueEnum)]
|
||||
pub enum OutputFormat {
|
||||
/// Print diagnostics verbosely, with context and helpful hints.
|
||||
///
|
||||
/// Diagnostic messages may include additional context and
|
||||
/// annotations on the input to help understand the message.
|
||||
#[default]
|
||||
#[value(name = "full")]
|
||||
Full,
|
||||
/// Print diagnostics concisely, one per line.
|
||||
///
|
||||
/// This will guarantee that each diagnostic is printed on
|
||||
/// a single line. Only the most important or primary aspects
|
||||
/// of the diagnostic are included. Contextual information is
|
||||
/// dropped.
|
||||
#[value(name = "concise")]
|
||||
Concise,
|
||||
}
|
||||
|
||||
impl From<OutputFormat> for ruff_db::diagnostic::DiagnosticFormat {
|
||||
fn from(format: OutputFormat) -> ruff_db::diagnostic::DiagnosticFormat {
|
||||
match format {
|
||||
OutputFormat::Full => Self::Full,
|
||||
OutputFormat::Concise => Self::Concise,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -256,6 +256,7 @@ impl MainLoop {
|
|||
revision: check_revision,
|
||||
} => {
|
||||
let display_config = DisplayDiagnosticConfig::default()
|
||||
.format(db.project().settings(db).terminal().output_format)
|
||||
.color(colored::control::SHOULD_COLORIZE.should_colorize());
|
||||
|
||||
let min_error_severity =
|
||||
|
|
|
@ -967,6 +967,30 @@ fn check_non_existing_path() -> anyhow::Result<()> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn concise_diagnostics() -> anyhow::Result<()> {
|
||||
let case = TestCase::with_file(
|
||||
"test.py",
|
||||
r#"
|
||||
print(x) # [unresolved-reference]
|
||||
print(4[1]) # [non-subscriptable]
|
||||
"#,
|
||||
)?;
|
||||
|
||||
assert_cmd_snapshot!(case.command().arg("--output-format=concise"), @r"
|
||||
success: false
|
||||
exit_code: 1
|
||||
----- stdout -----
|
||||
warning[lint:unresolved-reference] <temp_dir>/test.py:2:7: Name `x` used when not defined
|
||||
error[lint:non-subscriptable] <temp_dir>/test.py:3:7: Cannot subscript object of type `Literal[4]` with no `__getitem__` method
|
||||
Found 2 diagnostics
|
||||
|
||||
----- stderr -----
|
||||
");
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
struct TestCase {
|
||||
_temp_dir: TempDir,
|
||||
_settings_scope: SettingsBindDropGuard,
|
||||
|
|
|
@ -2,7 +2,7 @@ use crate::metadata::value::{RangedValue, RelativePathBuf, ValueSource, ValueSou
|
|||
use crate::Db;
|
||||
use red_knot_python_semantic::lint::{GetLintError, Level, LintSource, RuleSelection};
|
||||
use red_knot_python_semantic::{ProgramSettings, PythonPath, PythonPlatform, SearchPathSettings};
|
||||
use ruff_db::diagnostic::{DiagnosticId, OldDiagnosticTrait, Severity, Span};
|
||||
use ruff_db::diagnostic::{DiagnosticFormat, DiagnosticId, OldDiagnosticTrait, Severity, Span};
|
||||
use ruff_db::files::system_path_to_file;
|
||||
use ruff_db::system::{System, SystemPath};
|
||||
use ruff_macros::Combine;
|
||||
|
@ -120,6 +120,11 @@ impl Options {
|
|||
|
||||
if let Some(terminal) = self.terminal.as_ref() {
|
||||
settings.set_terminal(TerminalSettings {
|
||||
output_format: terminal
|
||||
.output_format
|
||||
.as_deref()
|
||||
.copied()
|
||||
.unwrap_or_default(),
|
||||
error_on_warning: terminal.error_on_warning.unwrap_or_default(),
|
||||
});
|
||||
}
|
||||
|
@ -277,6 +282,11 @@ impl FromIterator<(RangedValue<String>, RangedValue<Level>)> for Rules {
|
|||
#[serde(rename_all = "kebab-case", deny_unknown_fields)]
|
||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||
pub struct TerminalOptions {
|
||||
/// The format to use for printing diagnostic messages.
|
||||
///
|
||||
/// Defaults to `full`.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub output_format: Option<RangedValue<DiagnosticFormat>>,
|
||||
/// Use exit code 1 if there are any warning-level diagnostics.
|
||||
///
|
||||
/// Defaults to `false`.
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
use std::sync::Arc;
|
||||
|
||||
use red_knot_python_semantic::lint::RuleSelection;
|
||||
use ruff_db::diagnostic::DiagnosticFormat;
|
||||
|
||||
/// The resolved [`super::Options`] for the project.
|
||||
///
|
||||
|
@ -49,5 +50,6 @@ impl Settings {
|
|||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Default)]
|
||||
pub struct TerminalSettings {
|
||||
pub output_format: DiagnosticFormat,
|
||||
pub error_on_warning: bool,
|
||||
}
|
||||
|
|
|
@ -49,6 +49,25 @@
|
|||
},
|
||||
"additionalProperties": false,
|
||||
"definitions": {
|
||||
"DiagnosticFormat": {
|
||||
"description": "The diagnostic output format.",
|
||||
"oneOf": [
|
||||
{
|
||||
"description": "The default full mode will print \"pretty\" diagnostics.\n\nThat is, color will be used when printing to a `tty`. Moreover, diagnostic messages may include additional context and annotations on the input to help understand the message.",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"full"
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "Print diagnostics in a concise mode.\n\nThis will guarantee that each diagnostic is printed on a single line. Only the most important or primary aspects of the diagnostic are included. Contextual information is dropped.\n\nThis may use color when printing to a `tty`.",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"concise"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"EnvironmentOptions": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
|
@ -748,6 +767,17 @@
|
|||
"boolean",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"output-format": {
|
||||
"description": "The format to use for printing diagnostic messages.\n\nDefaults to `full`.",
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/DiagnosticFormat"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue