mirror of
https://github.com/astral-sh/ruff.git
synced 2025-09-30 05:45:24 +00:00
Better error message when --config
is given a table key and a non-inline-table value (#15266)
Co-authored-by: Micha Reiser <micha@reiser.io> Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
This commit is contained in:
parent
f29c9e48a4
commit
832c0fa04b
3 changed files with 132 additions and 5 deletions
|
@ -9,6 +9,7 @@ use anyhow::bail;
|
||||||
use clap::builder::{TypedValueParser, ValueParserFactory};
|
use clap::builder::{TypedValueParser, ValueParserFactory};
|
||||||
use clap::{command, Parser, Subcommand};
|
use clap::{command, Parser, Subcommand};
|
||||||
use colored::Colorize;
|
use colored::Colorize;
|
||||||
|
use itertools::Itertools;
|
||||||
use path_absolutize::path_dedot;
|
use path_absolutize::path_dedot;
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
use ruff_graph::Direction;
|
use ruff_graph::Direction;
|
||||||
|
@ -24,6 +25,7 @@ use ruff_source_file::{LineIndex, OneIndexed};
|
||||||
use ruff_text_size::TextRange;
|
use ruff_text_size::TextRange;
|
||||||
use ruff_workspace::configuration::{Configuration, RuleSelection};
|
use ruff_workspace::configuration::{Configuration, RuleSelection};
|
||||||
use ruff_workspace::options::{Options, PycodestyleOptions};
|
use ruff_workspace::options::{Options, PycodestyleOptions};
|
||||||
|
use ruff_workspace::options_base::{OptionEntry, OptionsMetadata};
|
||||||
use ruff_workspace::resolver::ConfigurationTransformer;
|
use ruff_workspace::resolver::ConfigurationTransformer;
|
||||||
use rustc_hash::FxHashMap;
|
use rustc_hash::FxHashMap;
|
||||||
use toml;
|
use toml;
|
||||||
|
@ -967,12 +969,37 @@ It looks like you were trying to pass a path to a configuration file.
|
||||||
The path `{value}` does not point to a configuration file"
|
The path `{value}` does not point to a configuration file"
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
} else if value.contains('=') {
|
} else if let Some((key, value)) = value.split_once('=') {
|
||||||
|
let key = key.trim_ascii();
|
||||||
|
let value = value.trim_ascii_start();
|
||||||
|
|
||||||
|
match Options::metadata().find(key) {
|
||||||
|
Some(OptionEntry::Set(set)) if !value.starts_with('{') => {
|
||||||
|
let prefixed_subfields = set
|
||||||
|
.collect_fields()
|
||||||
|
.iter()
|
||||||
|
.map(|(name, _)| format!("- `{key}.{name}`"))
|
||||||
|
.join("\n");
|
||||||
|
|
||||||
|
tip.push_str(&format!(
|
||||||
|
"
|
||||||
|
|
||||||
|
`{key}` is a table of configuration options.
|
||||||
|
Did you want to override one of the table's subkeys?
|
||||||
|
|
||||||
|
Possible choices:
|
||||||
|
|
||||||
|
{prefixed_subfields}"
|
||||||
|
));
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
tip.push_str(&format!(
|
tip.push_str(&format!(
|
||||||
"\n\n{}:\n\n{underlying_error}",
|
"\n\n{}:\n\n{underlying_error}",
|
||||||
config_parse_error.description()
|
config_parse_error.description()
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
let tip = tip.trim_end().to_owned().into();
|
let tip = tip.trim_end().to_owned().into();
|
||||||
|
|
||||||
new_error.insert(
|
new_error.insert(
|
||||||
|
|
|
@ -780,6 +780,90 @@ fn each_toml_option_requires_a_new_flag_2() {
|
||||||
");
|
");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn value_given_to_table_key_is_not_inline_table_1() {
|
||||||
|
// https://github.com/astral-sh/ruff/issues/13995
|
||||||
|
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
||||||
|
.args(STDIN_BASE_OPTIONS)
|
||||||
|
.args([".", "--config", r#"lint.flake8-pytest-style="csv""#]),
|
||||||
|
@r#"
|
||||||
|
success: false
|
||||||
|
exit_code: 2
|
||||||
|
----- stdout -----
|
||||||
|
|
||||||
|
----- stderr -----
|
||||||
|
error: invalid value 'lint.flake8-pytest-style="csv"' for '--config <CONFIG_OPTION>'
|
||||||
|
|
||||||
|
tip: A `--config` flag must either be a path to a `.toml` configuration file
|
||||||
|
or a TOML `<KEY> = <VALUE>` pair overriding a specific configuration
|
||||||
|
option
|
||||||
|
|
||||||
|
`lint.flake8-pytest-style` is a table of configuration options.
|
||||||
|
Did you want to override one of the table's subkeys?
|
||||||
|
|
||||||
|
Possible choices:
|
||||||
|
|
||||||
|
- `lint.flake8-pytest-style.fixture-parentheses`
|
||||||
|
- `lint.flake8-pytest-style.parametrize-names-type`
|
||||||
|
- `lint.flake8-pytest-style.parametrize-values-type`
|
||||||
|
- `lint.flake8-pytest-style.parametrize-values-row-type`
|
||||||
|
- `lint.flake8-pytest-style.raises-require-match-for`
|
||||||
|
- `lint.flake8-pytest-style.raises-extend-require-match-for`
|
||||||
|
- `lint.flake8-pytest-style.mark-parentheses`
|
||||||
|
|
||||||
|
For more information, try '--help'.
|
||||||
|
"#);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn value_given_to_table_key_is_not_inline_table_2() {
|
||||||
|
// https://github.com/astral-sh/ruff/issues/13995
|
||||||
|
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
||||||
|
.args(STDIN_BASE_OPTIONS)
|
||||||
|
.args([".", "--config", r#"lint=123"#]),
|
||||||
|
@r"
|
||||||
|
success: false
|
||||||
|
exit_code: 2
|
||||||
|
----- stdout -----
|
||||||
|
|
||||||
|
----- stderr -----
|
||||||
|
error: invalid value 'lint=123' for '--config <CONFIG_OPTION>'
|
||||||
|
|
||||||
|
tip: A `--config` flag must either be a path to a `.toml` configuration file
|
||||||
|
or a TOML `<KEY> = <VALUE>` pair overriding a specific configuration
|
||||||
|
option
|
||||||
|
|
||||||
|
`lint` is a table of configuration options.
|
||||||
|
Did you want to override one of the table's subkeys?
|
||||||
|
|
||||||
|
Possible choices:
|
||||||
|
|
||||||
|
- `lint.allowed-confusables`
|
||||||
|
- `lint.dummy-variable-rgx`
|
||||||
|
- `lint.extend-ignore`
|
||||||
|
- `lint.extend-select`
|
||||||
|
- `lint.extend-fixable`
|
||||||
|
- `lint.external`
|
||||||
|
- `lint.fixable`
|
||||||
|
- `lint.ignore`
|
||||||
|
- `lint.extend-safe-fixes`
|
||||||
|
- `lint.extend-unsafe-fixes`
|
||||||
|
- `lint.ignore-init-module-imports`
|
||||||
|
- `lint.logger-objects`
|
||||||
|
- `lint.select`
|
||||||
|
- `lint.explicit-preview-rules`
|
||||||
|
- `lint.task-tags`
|
||||||
|
- `lint.typing-modules`
|
||||||
|
- `lint.unfixable`
|
||||||
|
- `lint.per-file-ignores`
|
||||||
|
- `lint.extend-per-file-ignores`
|
||||||
|
- `lint.exclude`
|
||||||
|
- `lint.preview`
|
||||||
|
|
||||||
|
For more information, try '--help'.
|
||||||
|
");
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn config_doubly_overridden_via_cli() -> Result<()> {
|
fn config_doubly_overridden_via_cli() -> Result<()> {
|
||||||
let tempdir = TempDir::new()?;
|
let tempdir = TempDir::new()?;
|
||||||
|
|
|
@ -285,6 +285,22 @@ impl OptionSet {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn collect_fields(&self) -> Vec<(String, OptionField)> {
|
||||||
|
struct FieldsCollector(Vec<(String, OptionField)>);
|
||||||
|
|
||||||
|
impl Visit for FieldsCollector {
|
||||||
|
fn record_field(&mut self, name: &str, field: OptionField) {
|
||||||
|
self.0.push((name.to_string(), field));
|
||||||
|
}
|
||||||
|
|
||||||
|
fn record_set(&mut self, _name: &str, _group: OptionSet) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut visitor = FieldsCollector(vec![]);
|
||||||
|
self.record(&mut visitor);
|
||||||
|
visitor.0
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Visitor that writes out the names of all fields and sets.
|
/// Visitor that writes out the names of all fields and sets.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue