mirror of
https://github.com/astral-sh/ruff.git
synced 2025-09-29 13:25:17 +00:00
Refine the warnings about incompatible linter options (#8196)
## Summary Avoid warning about incompatible rules except if their configuration directly conflicts with the formatter. This should reduce the noise and potentially the need for https://github.com/astral-sh/ruff/issues/8175 and https://github.com/astral-sh/ruff/issues/8185 I also extended the rule and option documentation to mention any potential formatter incompatibilities or whether they're redundant when using the formatter. * `LineTooLong`: This is a use case we explicitly want to support. Don't warn about it * `TabIndentation`, `IndentWithSpaces`: Only warn if `indent-style="tab"` * `IndentationWithInvalidMultiple`, `IndentationWithInvalidMultipleComment`: Only warn if `indent-width != 4` * `OverIndented`: Don't warn, but mention that the rule is redundant * `BadQuotesInlineString`: Warn if quote setting is different from `format.quote-style` * `BadQuotesMultilineString`, `BadQuotesDocstring`: Warn if `quote != "double"` ## Test Plan I added a new integration test for the default configuration with `ALL`. `ruff format` now only shows two incompatible rules, which feels more reasonable.
This commit is contained in:
parent
be3307e9a6
commit
a4dd1e5fad
9 changed files with 247 additions and 49 deletions
|
@ -18,11 +18,11 @@ use ruff_diagnostics::SourceMap;
|
||||||
use ruff_linter::fs;
|
use ruff_linter::fs;
|
||||||
use ruff_linter::logging::LogLevel;
|
use ruff_linter::logging::LogLevel;
|
||||||
use ruff_linter::registry::Rule;
|
use ruff_linter::registry::Rule;
|
||||||
use ruff_linter::settings::rule_table::RuleTable;
|
use ruff_linter::rules::flake8_quotes::settings::Quote;
|
||||||
use ruff_linter::source_kind::{SourceError, SourceKind};
|
use ruff_linter::source_kind::{SourceError, SourceKind};
|
||||||
use ruff_linter::warn_user_once;
|
use ruff_linter::warn_user_once;
|
||||||
use ruff_python_ast::{PySourceType, SourceType};
|
use ruff_python_ast::{PySourceType, SourceType};
|
||||||
use ruff_python_formatter::{format_module_source, FormatModuleError};
|
use ruff_python_formatter::{format_module_source, FormatModuleError, QuoteStyle};
|
||||||
use ruff_text_size::{TextLen, TextRange, TextSize};
|
use ruff_text_size::{TextLen, TextRange, TextSize};
|
||||||
use ruff_workspace::resolver::{
|
use ruff_workspace::resolver::{
|
||||||
match_exclusion, python_files_in_path, PyprojectConfig, ResolvedFile, Resolver,
|
match_exclusion, python_files_in_path, PyprojectConfig, ResolvedFile, Resolver,
|
||||||
|
@ -700,53 +700,105 @@ pub(super) fn warn_incompatible_formatter_settings(
|
||||||
{
|
{
|
||||||
let mut incompatible_rules = Vec::new();
|
let mut incompatible_rules = Vec::new();
|
||||||
|
|
||||||
for incompatible_rule in RuleTable::from_iter([
|
for rule in [
|
||||||
Rule::LineTooLong,
|
// The formatter might collapse implicit string concatenation on a single line.
|
||||||
Rule::TabIndentation,
|
|
||||||
Rule::IndentationWithInvalidMultiple,
|
|
||||||
Rule::IndentationWithInvalidMultipleComment,
|
|
||||||
Rule::OverIndented,
|
|
||||||
Rule::IndentWithSpaces,
|
|
||||||
Rule::SingleLineImplicitStringConcatenation,
|
Rule::SingleLineImplicitStringConcatenation,
|
||||||
|
// Flags missing trailing commas when all arguments are on its own line:
|
||||||
|
// ```python
|
||||||
|
// def args(
|
||||||
|
// aaaaaaaa, bbbbbbbbb, cccccccccc, ddddddddd, eeeeeeee, ffffff, gggggggggggg, hhhh
|
||||||
|
// ):
|
||||||
|
// pass
|
||||||
|
// ```
|
||||||
Rule::MissingTrailingComma,
|
Rule::MissingTrailingComma,
|
||||||
Rule::ProhibitedTrailingComma,
|
] {
|
||||||
Rule::BadQuotesInlineString,
|
if setting.linter.rules.enabled(rule) {
|
||||||
Rule::BadQuotesMultilineString,
|
incompatible_rules.push(rule);
|
||||||
Rule::BadQuotesDocstring,
|
}
|
||||||
Rule::AvoidableEscapedQuote,
|
}
|
||||||
])
|
|
||||||
.iter_enabled()
|
// Rules asserting for space indentation
|
||||||
{
|
if setting.formatter.indent_style.is_tab() {
|
||||||
if setting.linter.rules.enabled(incompatible_rule) {
|
for rule in [Rule::TabIndentation, Rule::IndentWithSpaces] {
|
||||||
incompatible_rules.push(format!("'{}'", incompatible_rule.noqa_code()));
|
if setting.linter.rules.enabled(rule) {
|
||||||
|
incompatible_rules.push(rule);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Rules asserting for indent-width=4
|
||||||
|
if setting.formatter.indent_width.value() != 4 {
|
||||||
|
for rule in [
|
||||||
|
Rule::IndentationWithInvalidMultiple,
|
||||||
|
Rule::IndentationWithInvalidMultipleComment,
|
||||||
|
] {
|
||||||
|
if setting.linter.rules.enabled(rule) {
|
||||||
|
incompatible_rules.push(rule);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !incompatible_rules.is_empty() {
|
if !incompatible_rules.is_empty() {
|
||||||
incompatible_rules.sort();
|
let mut rule_names: Vec<_> = incompatible_rules
|
||||||
warn!("The following rules may cause conflicts when used with the formatter: {}. To avoid unexpected behavior, we recommend disabling these rules, either by removing them from the `select` or `extend-select` configuration, or adding then to the `ignore` configuration.", incompatible_rules.join(", "));
|
.into_iter()
|
||||||
|
.map(|rule| format!("`{}`", rule.noqa_code()))
|
||||||
|
.collect();
|
||||||
|
rule_names.sort();
|
||||||
|
warn!("The following rules may cause conflicts when used with the formatter: {}. To avoid unexpected behavior, we recommend disabling these rules, either by removing them from the `select` or `extend-select` configuration, or adding then to the `ignore` configuration.", rule_names.join(", "));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Rules with different quote styles.
|
||||||
|
if setting
|
||||||
|
.linter
|
||||||
|
.rules
|
||||||
|
.any_enabled(&[Rule::BadQuotesInlineString, Rule::AvoidableEscapedQuote])
|
||||||
|
{
|
||||||
|
match (
|
||||||
|
setting.linter.flake8_quotes.inline_quotes,
|
||||||
|
setting.formatter.quote_style,
|
||||||
|
) {
|
||||||
|
(Quote::Double, QuoteStyle::Single) => {
|
||||||
|
warn!("The `flake8-quotes.inline-quotes=\"double\"` option is incompatible with the formatter's `format.quote-style=\"single\"`. We recommend disabling `Q000` and `Q003` when using the formatter, which enforces a consistent quote style. Alternatively, set both options to either `\"single\"` or `\"double\"`.");
|
||||||
|
}
|
||||||
|
(Quote::Single, QuoteStyle::Double) => {
|
||||||
|
warn!("The `flake8-quotes.inline-quotes=\"single\"` option is incompatible with the formatter's `format.quote-style=\"double\"`. We recommend disabling `Q000` and `Q003` when using the formatter, which enforces a consistent quote style. Alternatively, set both options to either `\"single\"` or `\"double\"`.");
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if setting.linter.rules.enabled(Rule::BadQuotesMultilineString)
|
||||||
|
&& setting.linter.flake8_quotes.multiline_quotes == Quote::Single
|
||||||
|
{
|
||||||
|
warn!("The `flake8-quotes.multiline-quotes=\"single\"` option is incompatible with the formatter. We recommend disabling `Q001` when using the formatter, which enforces double quotes for multiline strings. Alternatively, set the `flake8-quotes.multiline-quotes` option to `\"double\"`.`");
|
||||||
|
}
|
||||||
|
|
||||||
|
if setting.linter.rules.enabled(Rule::BadQuotesDocstring)
|
||||||
|
&& setting.linter.flake8_quotes.docstring_quotes == Quote::Single
|
||||||
|
{
|
||||||
|
warn!("The `flake8-quotes.multiline-quotes=\"single\"` option is incompatible with the formatter. We recommend disabling `Q002` when using the formatter, which enforces double quotes for docstrings. Alternatively, set the `flake8-quotes.docstring-quotes` option to `\"double\"`.`");
|
||||||
}
|
}
|
||||||
|
|
||||||
if setting.linter.rules.enabled(Rule::UnsortedImports) {
|
if setting.linter.rules.enabled(Rule::UnsortedImports) {
|
||||||
// The formatter removes empty lines if the value is larger than 2 but always inserts a empty line after imports.
|
// The formatter removes empty lines if the value is larger than 2 but always inserts a empty line after imports.
|
||||||
// Two empty lines are okay because `isort` only uses this setting for top-level imports (not in nested blocks).
|
// Two empty lines are okay because `isort` only uses this setting for top-level imports (not in nested blocks).
|
||||||
if !matches!(setting.linter.isort.lines_after_imports, 1 | 2 | -1) {
|
if !matches!(setting.linter.isort.lines_after_imports, 1 | 2 | -1) {
|
||||||
warn!("The isort option 'isort.lines-after-imports' with a value other than `-1`, `1` or `2` is incompatible with the formatter. To avoid unexpected behavior, we recommend setting the option to one of: `2`, `1`, or `-1` (default).");
|
warn!("The isort option `isort.lines-after-imports` with a value other than `-1`, `1` or `2` is incompatible with the formatter. To avoid unexpected behavior, we recommend setting the option to one of: `2`, `1`, or `-1` (default).");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Values larger than two get reduced to one line by the formatter if the import is in a nested block.
|
// Values larger than two get reduced to one line by the formatter if the import is in a nested block.
|
||||||
if setting.linter.isort.lines_between_types > 1 {
|
if setting.linter.isort.lines_between_types > 1 {
|
||||||
warn!("The isort option 'isort.lines-between-types' with a value larger than 1 is incompatible with the formatter. To avoid unexpected behavior, we recommend setting the option to one of: `1` or `0` (default).");
|
warn!("The isort option `isort.lines-between-types` with a value greater than 1 is incompatible with the formatter. To avoid unexpected behavior, we recommend setting the option to one of: `1` or `0` (default).");
|
||||||
}
|
}
|
||||||
|
|
||||||
// isort inserts a trailing comma which the formatter preserves, but only if `skip-magic-trailing-comma` isn't false.
|
// isort inserts a trailing comma which the formatter preserves, but only if `skip-magic-trailing-comma` isn't false.
|
||||||
if setting.formatter.magic_trailing_comma.is_ignore() {
|
if setting.formatter.magic_trailing_comma.is_ignore() {
|
||||||
if setting.linter.isort.force_wrap_aliases {
|
if setting.linter.isort.force_wrap_aliases {
|
||||||
warn!("The isort option 'isort.force-wrap-aliases' is incompatible with the formatter 'format.skip-magic-trailing-comma=true' option. To avoid unexpected behavior, we recommend either setting 'isort.force-wrap-aliases=false' or 'format.skip-magic-trailing-comma=false'.");
|
warn!("The isort option `isort.force-wrap-aliases` is incompatible with the formatter `format.skip-magic-trailing-comma=true` option. To avoid unexpected behavior, we recommend either setting `isort.force-wrap-aliases=false` or `format.skip-magic-trailing-comma=false`.");
|
||||||
}
|
}
|
||||||
|
|
||||||
if setting.linter.isort.split_on_trailing_comma {
|
if setting.linter.isort.split_on_trailing_comma {
|
||||||
warn!("The isort option 'isort.split-on-trailing-comma' is incompatible with the formatter 'format.skip-magic-trailing-comma=true' option. To avoid unexpected behavior, we recommend either setting 'isort.split-on-trailing-comma=false' or 'format.skip-magic-trailing-comma=false'.");
|
warn!("The isort option `isort.split-on-trailing-comma` is incompatible with the formatter `format.skip-magic-trailing-comma=true` option. To avoid unexpected behavior, we recommend either setting `isort.split-on-trailing-comma=false` or `format.skip-magic-trailing-comma=false`.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -230,7 +230,9 @@ fn format_option_inheritance() -> Result<()> {
|
||||||
&ruff_toml,
|
&ruff_toml,
|
||||||
r#"
|
r#"
|
||||||
extend = "base.toml"
|
extend = "base.toml"
|
||||||
extend-select = ["Q000"]
|
|
||||||
|
[lint]
|
||||||
|
extend-select = ["COM812"]
|
||||||
|
|
||||||
[format]
|
[format]
|
||||||
quote-style = "single"
|
quote-style = "single"
|
||||||
|
@ -273,7 +275,7 @@ if condition:
|
||||||
print('Should change quotes')
|
print('Should change quotes')
|
||||||
|
|
||||||
----- stderr -----
|
----- stderr -----
|
||||||
warning: The following rules may cause conflicts when used with the formatter: 'Q000'. To avoid unexpected behavior, we recommend disabling these rules, either by removing them from the `select` or `extend-select` configuration, or adding then to the `ignore` configuration.
|
warning: The following rules may cause conflicts when used with the formatter: `COM812`. To avoid unexpected behavior, we recommend disabling these rules, either by removing them from the `select` or `extend-select` configuration, or adding then to the `ignore` configuration.
|
||||||
"###);
|
"###);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -359,18 +361,27 @@ fn conflicting_options() -> Result<()> {
|
||||||
fs::write(
|
fs::write(
|
||||||
&ruff_toml,
|
&ruff_toml,
|
||||||
r#"
|
r#"
|
||||||
|
indent-width = 2
|
||||||
|
|
||||||
|
[lint]
|
||||||
select = ["ALL"]
|
select = ["ALL"]
|
||||||
ignore = ["D203", "D212"]
|
ignore = ["D203", "D212"]
|
||||||
|
|
||||||
[isort]
|
[lint.isort]
|
||||||
lines-after-imports = 3
|
lines-after-imports = 3
|
||||||
lines-between-types = 2
|
lines-between-types = 2
|
||||||
force-wrap-aliases = true
|
force-wrap-aliases = true
|
||||||
combine-as-imports = true
|
combine-as-imports = true
|
||||||
split-on-trailing-comma = true
|
split-on-trailing-comma = true
|
||||||
|
|
||||||
|
[lint.flake8-quotes]
|
||||||
|
inline-quotes = "single"
|
||||||
|
docstring-quotes = "single"
|
||||||
|
multiline-quotes = "single"
|
||||||
|
|
||||||
[format]
|
[format]
|
||||||
skip-magic-trailing-comma = true
|
skip-magic-trailing-comma = true
|
||||||
|
indent-style = "tab"
|
||||||
"#,
|
"#,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
|
@ -392,11 +403,14 @@ def say_hy(name: str):
|
||||||
1 file reformatted
|
1 file reformatted
|
||||||
|
|
||||||
----- stderr -----
|
----- stderr -----
|
||||||
warning: The following rules may cause conflicts when used with the formatter: 'COM812', 'COM819', 'D206', 'E501', 'ISC001', 'Q000', 'Q001', 'Q002', 'Q003', 'W191'. To avoid unexpected behavior, we recommend disabling these rules, either by removing them from the `select` or `extend-select` configuration, or adding then to the `ignore` configuration.
|
warning: The following rules may cause conflicts when used with the formatter: `COM812`, `D206`, `ISC001`, `W191`. To avoid unexpected behavior, we recommend disabling these rules, either by removing them from the `select` or `extend-select` configuration, or adding then to the `ignore` configuration.
|
||||||
warning: The isort option 'isort.lines-after-imports' with a value other than `-1`, `1` or `2` is incompatible with the formatter. To avoid unexpected behavior, we recommend setting the option to one of: `2`, `1`, or `-1` (default).
|
warning: The `flake8-quotes.inline-quotes="single"` option is incompatible with the formatter's `format.quote-style="double"`. We recommend disabling `Q000` and `Q003` when using the formatter, which enforces a consistent quote style. Alternatively, set both options to either `"single"` or `"double"`.
|
||||||
warning: The isort option 'isort.lines-between-types' with a value larger than 1 is incompatible with the formatter. To avoid unexpected behavior, we recommend setting the option to one of: `1` or `0` (default).
|
warning: The `flake8-quotes.multiline-quotes="single"` option is incompatible with the formatter. We recommend disabling `Q001` when using the formatter, which enforces double quotes for multiline strings. Alternatively, set the `flake8-quotes.multiline-quotes` option to `"double"`.`
|
||||||
warning: The isort option 'isort.force-wrap-aliases' is incompatible with the formatter 'format.skip-magic-trailing-comma=true' option. To avoid unexpected behavior, we recommend either setting 'isort.force-wrap-aliases=false' or 'format.skip-magic-trailing-comma=false'.
|
warning: The `flake8-quotes.multiline-quotes="single"` option is incompatible with the formatter. We recommend disabling `Q002` when using the formatter, which enforces double quotes for docstrings. Alternatively, set the `flake8-quotes.docstring-quotes` option to `"double"`.`
|
||||||
warning: The isort option 'isort.split-on-trailing-comma' is incompatible with the formatter 'format.skip-magic-trailing-comma=true' option. To avoid unexpected behavior, we recommend either setting 'isort.split-on-trailing-comma=false' or 'format.skip-magic-trailing-comma=false'.
|
warning: The isort option `isort.lines-after-imports` with a value other than `-1`, `1` or `2` is incompatible with the formatter. To avoid unexpected behavior, we recommend setting the option to one of: `2`, `1`, or `-1` (default).
|
||||||
|
warning: The isort option `isort.lines-between-types` with a value greater than 1 is incompatible with the formatter. To avoid unexpected behavior, we recommend setting the option to one of: `1` or `0` (default).
|
||||||
|
warning: The isort option `isort.force-wrap-aliases` is incompatible with the formatter `format.skip-magic-trailing-comma=true` option. To avoid unexpected behavior, we recommend either setting `isort.force-wrap-aliases=false` or `format.skip-magic-trailing-comma=false`.
|
||||||
|
warning: The isort option `isort.split-on-trailing-comma` is incompatible with the formatter `format.skip-magic-trailing-comma=true` option. To avoid unexpected behavior, we recommend either setting `isort.split-on-trailing-comma=false` or `format.skip-magic-trailing-comma=false`.
|
||||||
"###);
|
"###);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -408,18 +422,27 @@ fn conflicting_options_stdin() -> Result<()> {
|
||||||
fs::write(
|
fs::write(
|
||||||
&ruff_toml,
|
&ruff_toml,
|
||||||
r#"
|
r#"
|
||||||
|
indent-width = 2
|
||||||
|
|
||||||
|
[lint]
|
||||||
select = ["ALL"]
|
select = ["ALL"]
|
||||||
ignore = ["D203", "D212"]
|
ignore = ["D203", "D212"]
|
||||||
|
|
||||||
[isort]
|
[lint.isort]
|
||||||
lines-after-imports = 3
|
lines-after-imports = 3
|
||||||
lines-between-types = 2
|
lines-between-types = 2
|
||||||
force-wrap-aliases = true
|
force-wrap-aliases = true
|
||||||
combine-as-imports = true
|
combine-as-imports = true
|
||||||
split-on-trailing-comma = true
|
split-on-trailing-comma = true
|
||||||
|
|
||||||
|
[lint.flake8-quotes]
|
||||||
|
inline-quotes = "single"
|
||||||
|
docstring-quotes = "single"
|
||||||
|
multiline-quotes = "single"
|
||||||
|
|
||||||
[format]
|
[format]
|
||||||
skip-magic-trailing-comma = true
|
skip-magic-trailing-comma = true
|
||||||
|
indent-style = "tab"
|
||||||
"#,
|
"#,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
|
@ -434,14 +457,17 @@ def say_hy(name: str):
|
||||||
exit_code: 0
|
exit_code: 0
|
||||||
----- stdout -----
|
----- stdout -----
|
||||||
def say_hy(name: str):
|
def say_hy(name: str):
|
||||||
print(f"Hy {name}")
|
print(f"Hy {name}")
|
||||||
|
|
||||||
----- stderr -----
|
----- stderr -----
|
||||||
warning: The following rules may cause conflicts when used with the formatter: 'COM812', 'COM819', 'D206', 'E501', 'ISC001', 'Q000', 'Q001', 'Q002', 'Q003', 'W191'. To avoid unexpected behavior, we recommend disabling these rules, either by removing them from the `select` or `extend-select` configuration, or adding then to the `ignore` configuration.
|
warning: The following rules may cause conflicts when used with the formatter: `COM812`, `D206`, `ISC001`, `W191`. To avoid unexpected behavior, we recommend disabling these rules, either by removing them from the `select` or `extend-select` configuration, or adding then to the `ignore` configuration.
|
||||||
warning: The isort option 'isort.lines-after-imports' with a value other than `-1`, `1` or `2` is incompatible with the formatter. To avoid unexpected behavior, we recommend setting the option to one of: `2`, `1`, or `-1` (default).
|
warning: The `flake8-quotes.inline-quotes="single"` option is incompatible with the formatter's `format.quote-style="double"`. We recommend disabling `Q000` and `Q003` when using the formatter, which enforces a consistent quote style. Alternatively, set both options to either `"single"` or `"double"`.
|
||||||
warning: The isort option 'isort.lines-between-types' with a value larger than 1 is incompatible with the formatter. To avoid unexpected behavior, we recommend setting the option to one of: `1` or `0` (default).
|
warning: The `flake8-quotes.multiline-quotes="single"` option is incompatible with the formatter. We recommend disabling `Q001` when using the formatter, which enforces double quotes for multiline strings. Alternatively, set the `flake8-quotes.multiline-quotes` option to `"double"`.`
|
||||||
warning: The isort option 'isort.force-wrap-aliases' is incompatible with the formatter 'format.skip-magic-trailing-comma=true' option. To avoid unexpected behavior, we recommend either setting 'isort.force-wrap-aliases=false' or 'format.skip-magic-trailing-comma=false'.
|
warning: The `flake8-quotes.multiline-quotes="single"` option is incompatible with the formatter. We recommend disabling `Q002` when using the formatter, which enforces double quotes for docstrings. Alternatively, set the `flake8-quotes.docstring-quotes` option to `"double"`.`
|
||||||
warning: The isort option 'isort.split-on-trailing-comma' is incompatible with the formatter 'format.skip-magic-trailing-comma=true' option. To avoid unexpected behavior, we recommend either setting 'isort.split-on-trailing-comma=false' or 'format.skip-magic-trailing-comma=false'.
|
warning: The isort option `isort.lines-after-imports` with a value other than `-1`, `1` or `2` is incompatible with the formatter. To avoid unexpected behavior, we recommend setting the option to one of: `2`, `1`, or `-1` (default).
|
||||||
|
warning: The isort option `isort.lines-between-types` with a value greater than 1 is incompatible with the formatter. To avoid unexpected behavior, we recommend setting the option to one of: `1` or `0` (default).
|
||||||
|
warning: The isort option `isort.force-wrap-aliases` is incompatible with the formatter `format.skip-magic-trailing-comma=true` option. To avoid unexpected behavior, we recommend either setting `isort.force-wrap-aliases=false` or `format.skip-magic-trailing-comma=false`.
|
||||||
|
warning: The isort option `isort.split-on-trailing-comma` is incompatible with the formatter `format.skip-magic-trailing-comma=true` option. To avoid unexpected behavior, we recommend either setting `isort.split-on-trailing-comma=false` or `format.skip-magic-trailing-comma=false`.
|
||||||
"###);
|
"###);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -453,18 +479,25 @@ fn valid_linter_options() -> Result<()> {
|
||||||
fs::write(
|
fs::write(
|
||||||
&ruff_toml,
|
&ruff_toml,
|
||||||
r#"
|
r#"
|
||||||
|
[lint]
|
||||||
select = ["ALL"]
|
select = ["ALL"]
|
||||||
ignore = ["D203", "D212"]
|
ignore = ["D203", "D212", "COM812", "ISC001"]
|
||||||
|
|
||||||
[isort]
|
[lint.isort]
|
||||||
lines-after-imports = 2
|
lines-after-imports = 2
|
||||||
lines-between-types = 1
|
lines-between-types = 1
|
||||||
force-wrap-aliases = true
|
force-wrap-aliases = true
|
||||||
combine-as-imports = true
|
combine-as-imports = true
|
||||||
split-on-trailing-comma = true
|
split-on-trailing-comma = true
|
||||||
|
|
||||||
|
[lint.flake8-quotes]
|
||||||
|
inline-quotes = "single"
|
||||||
|
docstring-quotes = "double"
|
||||||
|
multiline-quotes = "double"
|
||||||
|
|
||||||
[format]
|
[format]
|
||||||
skip-magic-trailing-comma = false
|
skip-magic-trailing-comma = false
|
||||||
|
quote-style = "single"
|
||||||
"#,
|
"#,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
|
@ -486,10 +519,48 @@ def say_hy(name: str):
|
||||||
1 file reformatted
|
1 file reformatted
|
||||||
|
|
||||||
----- stderr -----
|
----- stderr -----
|
||||||
warning: The following rules may cause conflicts when used with the formatter: 'COM812', 'COM819', 'D206', 'E501', 'ISC001', 'Q000', 'Q001', 'Q002', 'Q003', 'W191'. To avoid unexpected behavior, we recommend disabling these rules, either by removing them from the `select` or `extend-select` configuration, or adding then to the `ignore` configuration.
|
|
||||||
"###);
|
"###);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn all_rules_default_options() -> Result<()> {
|
||||||
|
let tempdir = TempDir::new()?;
|
||||||
|
let ruff_toml = tempdir.path().join("ruff.toml");
|
||||||
|
|
||||||
|
fs::write(
|
||||||
|
&ruff_toml,
|
||||||
|
r#"
|
||||||
|
[lint]
|
||||||
|
select = ["ALL"]
|
||||||
|
"#,
|
||||||
|
)?;
|
||||||
|
|
||||||
|
let test_path = tempdir.path().join("test.py");
|
||||||
|
fs::write(
|
||||||
|
&test_path,
|
||||||
|
r#"
|
||||||
|
def say_hy(name: str):
|
||||||
|
print(f"Hy {name}")"#,
|
||||||
|
)?;
|
||||||
|
|
||||||
|
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
||||||
|
.args(["format", "--no-cache", "--config"])
|
||||||
|
.arg(&ruff_toml)
|
||||||
|
.arg(test_path), @r###"
|
||||||
|
success: true
|
||||||
|
exit_code: 0
|
||||||
|
----- stdout -----
|
||||||
|
1 file reformatted
|
||||||
|
|
||||||
|
----- stderr -----
|
||||||
|
warning: `one-blank-line-before-class` (D203) and `no-blank-line-before-class` (D211) are incompatible. Ignoring `one-blank-line-before-class`.
|
||||||
|
warning: `multi-line-summary-first-line` (D212) and `multi-line-summary-second-line` (D213) are incompatible. Ignoring `multi-line-summary-second-line`.
|
||||||
|
warning: The following rules may cause conflicts when used with the formatter: `COM812`, `ISC001`. To avoid unexpected behavior, we recommend disabling these rules, either by removing them from the `select` or `extend-select` configuration, or adding then to the `ignore` configuration.
|
||||||
|
"###);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_diff() {
|
fn test_diff() {
|
||||||
let args = ["format", "--no-cache", "--isolated", "--diff"];
|
let args = ["format", "--no-cache", "--isolated", "--diff"];
|
||||||
|
|
|
@ -27,6 +27,13 @@ use crate::settings::LinterSettings;
|
||||||
/// ```python
|
/// ```python
|
||||||
/// foo = "bar's"
|
/// foo = "bar's"
|
||||||
/// ```
|
/// ```
|
||||||
|
///
|
||||||
|
/// ## Formatter compatibility
|
||||||
|
/// We recommend against using this rule alongside the [formatter]. The
|
||||||
|
/// formatter automatically removes unnecessary escapes, making the rule
|
||||||
|
/// redundant.
|
||||||
|
///
|
||||||
|
/// [formatter]: https://docs.astral.sh/ruff/formatter
|
||||||
#[violation]
|
#[violation]
|
||||||
pub struct AvoidableEscapedQuote;
|
pub struct AvoidableEscapedQuote;
|
||||||
|
|
||||||
|
|
|
@ -32,6 +32,13 @@ use super::super::settings::Quote;
|
||||||
///
|
///
|
||||||
/// ## Options
|
/// ## Options
|
||||||
/// - `flake8-quotes.inline-quotes`
|
/// - `flake8-quotes.inline-quotes`
|
||||||
|
///
|
||||||
|
/// ## Formatter compatibility
|
||||||
|
/// We recommend against using this rule alongside the [formatter]. The
|
||||||
|
/// formatter enforces consistent quotes for inline strings, making the rule
|
||||||
|
/// redundant.
|
||||||
|
///
|
||||||
|
/// [formatter]: https://docs.astral.sh/ruff/formatter
|
||||||
#[violation]
|
#[violation]
|
||||||
pub struct BadQuotesInlineString {
|
pub struct BadQuotesInlineString {
|
||||||
preferred_quote: Quote,
|
preferred_quote: Quote,
|
||||||
|
@ -81,6 +88,13 @@ impl AlwaysFixableViolation for BadQuotesInlineString {
|
||||||
///
|
///
|
||||||
/// ## Options
|
/// ## Options
|
||||||
/// - `flake8-quotes.multiline-quotes`
|
/// - `flake8-quotes.multiline-quotes`
|
||||||
|
///
|
||||||
|
/// ## Formatter compatibility
|
||||||
|
/// We recommend against using this rule alongside the [formatter]. The
|
||||||
|
/// formatter enforces double quotes for multiline strings, making the rule
|
||||||
|
/// redundant.
|
||||||
|
///
|
||||||
|
/// [formatter]: https://docs.astral.sh/ruff/formatter
|
||||||
#[violation]
|
#[violation]
|
||||||
pub struct BadQuotesMultilineString {
|
pub struct BadQuotesMultilineString {
|
||||||
preferred_quote: Quote,
|
preferred_quote: Quote,
|
||||||
|
@ -129,6 +143,13 @@ impl AlwaysFixableViolation for BadQuotesMultilineString {
|
||||||
///
|
///
|
||||||
/// ## Options
|
/// ## Options
|
||||||
/// - `flake8-quotes.docstring-quotes`
|
/// - `flake8-quotes.docstring-quotes`
|
||||||
|
///
|
||||||
|
/// ## Formatter compatibility
|
||||||
|
/// We recommend against using this rule alongside the [formatter]. The
|
||||||
|
/// formatter enforces double quotes for docstrings, making the rule
|
||||||
|
/// redundant.
|
||||||
|
///
|
||||||
|
/// [formatter]: https://docs.astral.sh/ruff/formatter
|
||||||
#[violation]
|
#[violation]
|
||||||
pub struct BadQuotesDocstring {
|
pub struct BadQuotesDocstring {
|
||||||
preferred_quote: Quote,
|
preferred_quote: Quote,
|
||||||
|
|
|
@ -23,7 +23,16 @@ use super::LogicalLine;
|
||||||
/// a = 1
|
/// a = 1
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
|
///
|
||||||
|
/// ## Formatter compatibility
|
||||||
|
/// We recommend against using this rule alongside the [formatter]. The
|
||||||
|
/// formatter enforces consistent indentation, making the rule redundant.
|
||||||
|
///
|
||||||
|
/// The rule is also incompatible with the [formatter] when using
|
||||||
|
/// `indent-width` with a value other than `4`.
|
||||||
|
///
|
||||||
/// [PEP 8]: https://peps.python.org/pep-0008/#indentation
|
/// [PEP 8]: https://peps.python.org/pep-0008/#indentation
|
||||||
|
/// [formatter]:https://docs.astral.sh/ruff/formatter/
|
||||||
#[violation]
|
#[violation]
|
||||||
pub struct IndentationWithInvalidMultiple {
|
pub struct IndentationWithInvalidMultiple {
|
||||||
indent_size: usize,
|
indent_size: usize,
|
||||||
|
@ -55,7 +64,15 @@ impl Violation for IndentationWithInvalidMultiple {
|
||||||
/// # a = 1
|
/// # a = 1
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
|
/// ## Formatter compatibility
|
||||||
|
/// We recommend against using this rule alongside the [formatter]. The
|
||||||
|
/// formatter enforces consistent indentation, making the rule redundant.
|
||||||
|
///
|
||||||
|
/// The rule is also incompatible with the [formatter] when using
|
||||||
|
/// `indent-width` with a value other than `4`.
|
||||||
|
///
|
||||||
/// [PEP 8]: https://peps.python.org/pep-0008/#indentation
|
/// [PEP 8]: https://peps.python.org/pep-0008/#indentation
|
||||||
|
/// [formatter]:https://docs.astral.sh/ruff/formatter/
|
||||||
#[violation]
|
#[violation]
|
||||||
pub struct IndentationWithInvalidMultipleComment {
|
pub struct IndentationWithInvalidMultipleComment {
|
||||||
indent_size: usize,
|
indent_size: usize,
|
||||||
|
|
|
@ -26,7 +26,15 @@ use ruff_text_size::{TextLen, TextRange, TextSize};
|
||||||
/// a = 1
|
/// a = 1
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
|
/// ## Formatter compatibility
|
||||||
|
/// We recommend against using this rule alongside the [formatter]. The
|
||||||
|
/// formatter enforces consistent indentation, making the rule redundant.
|
||||||
|
///
|
||||||
|
/// The rule is also incompatible with the [formatter] when using
|
||||||
|
/// `format.indent-style="tab"`.
|
||||||
|
///
|
||||||
/// [PEP 8]: https://peps.python.org/pep-0008/#tabs-or-spaces
|
/// [PEP 8]: https://peps.python.org/pep-0008/#tabs-or-spaces
|
||||||
|
/// [formatter]: https://docs.astral.sh/ruff/formatter
|
||||||
#[violation]
|
#[violation]
|
||||||
pub struct TabIndentation;
|
pub struct TabIndentation;
|
||||||
|
|
||||||
|
|
|
@ -14,9 +14,7 @@ use crate::registry::Rule;
|
||||||
/// Checks for docstrings that are indented with tabs.
|
/// Checks for docstrings that are indented with tabs.
|
||||||
///
|
///
|
||||||
/// ## Why is this bad?
|
/// ## Why is this bad?
|
||||||
/// [PEP 8](https://peps.python.org/pep-0008/#tabs-or-spaces) recommends using
|
/// [PEP 8] recommends using spaces over tabs for indentation.
|
||||||
/// spaces over tabs for indentation.
|
|
||||||
///
|
|
||||||
///
|
///
|
||||||
/// ## Example
|
/// ## Example
|
||||||
/// ```python
|
/// ```python
|
||||||
|
@ -38,10 +36,20 @@ use crate::registry::Rule;
|
||||||
/// """
|
/// """
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
|
/// ## Formatter compatibility
|
||||||
|
/// We recommend against using this rule alongside the [formatter]. The
|
||||||
|
/// formatter enforces consistent indentation, making the rule redundant.
|
||||||
|
///
|
||||||
|
/// The rule is also incompatible with the [formatter] when using
|
||||||
|
/// `format.indent-style="tab"`.
|
||||||
|
///
|
||||||
/// ## References
|
/// ## References
|
||||||
/// - [PEP 257 – Docstring Conventions](https://peps.python.org/pep-0257/)
|
/// - [PEP 257 – Docstring Conventions](https://peps.python.org/pep-0257/)
|
||||||
/// - [NumPy Style Guide](https://numpydoc.readthedocs.io/en/latest/format.html)
|
/// - [NumPy Style Guide](https://numpydoc.readthedocs.io/en/latest/format.html)
|
||||||
/// - [Google Python Style Guide - Docstrings](https://google.github.io/styleguide/pyguide.html#38-comments-and-docstrings)
|
/// - [Google Python Style Guide - Docstrings](https://google.github.io/styleguide/pyguide.html#38-comments-and-docstrings)
|
||||||
|
///
|
||||||
|
/// [PEP 8]: https://peps.python.org/pep-0008/#tabs-or-spaces
|
||||||
|
/// [formatter]: https://docs.astral.sh/ruff/formatter
|
||||||
#[violation]
|
#[violation]
|
||||||
pub struct IndentWithSpaces;
|
pub struct IndentWithSpaces;
|
||||||
|
|
||||||
|
@ -126,12 +134,17 @@ impl AlwaysFixableViolation for UnderIndentation {
|
||||||
/// """
|
/// """
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
|
/// ## Formatter compatibility
|
||||||
|
/// We recommend against using this rule alongside the [formatter]. The
|
||||||
|
/// formatter enforces consistent indentation, making the rule redundant.
|
||||||
|
///
|
||||||
/// ## References
|
/// ## References
|
||||||
/// - [PEP 257 – Docstring Conventions](https://peps.python.org/pep-0257/)
|
/// - [PEP 257 – Docstring Conventions](https://peps.python.org/pep-0257/)
|
||||||
/// - [NumPy Style Guide](https://numpydoc.readthedocs.io/en/latest/format.html)
|
/// - [NumPy Style Guide](https://numpydoc.readthedocs.io/en/latest/format.html)
|
||||||
/// - [Google Python Style Guide - Docstrings](https://google.github.io/styleguide/pyguide.html#38-comments-and-docstrings)
|
/// - [Google Python Style Guide - Docstrings](https://google.github.io/styleguide/pyguide.html#38-comments-and-docstrings)
|
||||||
///
|
///
|
||||||
/// [PEP 257]: https://peps.python.org/pep-0257/
|
/// [PEP 257]: https://peps.python.org/pep-0257/
|
||||||
|
/// [formatter]:https://docs.astral.sh/ruff/formatter/
|
||||||
#[violation]
|
#[violation]
|
||||||
pub struct OverIndentation;
|
pub struct OverIndentation;
|
||||||
|
|
||||||
|
|
|
@ -1412,6 +1412,9 @@ impl Flake8PytestStyleOptions {
|
||||||
pub struct Flake8QuotesOptions {
|
pub struct Flake8QuotesOptions {
|
||||||
/// Quote style to prefer for inline strings (either "single" or
|
/// Quote style to prefer for inline strings (either "single" or
|
||||||
/// "double").
|
/// "double").
|
||||||
|
///
|
||||||
|
/// When using the formatter, ensure that `format.quote-style` is set to
|
||||||
|
/// the same preferred quote style.
|
||||||
#[option(
|
#[option(
|
||||||
default = r#""double""#,
|
default = r#""double""#,
|
||||||
value_type = r#""single" | "double""#,
|
value_type = r#""single" | "double""#,
|
||||||
|
@ -1423,6 +1426,9 @@ pub struct Flake8QuotesOptions {
|
||||||
|
|
||||||
/// Quote style to prefer for multiline strings (either "single" or
|
/// Quote style to prefer for multiline strings (either "single" or
|
||||||
/// "double").
|
/// "double").
|
||||||
|
///
|
||||||
|
/// When using the formatter, only "double" is compatible, as the formatter
|
||||||
|
/// enforces double quotes for multiline strings.
|
||||||
#[option(
|
#[option(
|
||||||
default = r#""double""#,
|
default = r#""double""#,
|
||||||
value_type = r#""single" | "double""#,
|
value_type = r#""single" | "double""#,
|
||||||
|
@ -1433,6 +1439,9 @@ pub struct Flake8QuotesOptions {
|
||||||
pub multiline_quotes: Option<Quote>,
|
pub multiline_quotes: Option<Quote>,
|
||||||
|
|
||||||
/// Quote style to prefer for docstrings (either "single" or "double").
|
/// Quote style to prefer for docstrings (either "single" or "double").
|
||||||
|
///
|
||||||
|
/// When using the formatter, only "double" is compatible, as the formatter
|
||||||
|
/// enforces double quotes for docstrings strings.
|
||||||
#[option(
|
#[option(
|
||||||
default = r#""double""#,
|
default = r#""double""#,
|
||||||
value_type = r#""single" | "double""#,
|
value_type = r#""single" | "double""#,
|
||||||
|
|
6
ruff.schema.json
generated
6
ruff.schema.json
generated
|
@ -1083,7 +1083,7 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"docstring-quotes": {
|
"docstring-quotes": {
|
||||||
"description": "Quote style to prefer for docstrings (either \"single\" or \"double\").",
|
"description": "Quote style to prefer for docstrings (either \"single\" or \"double\").\n\nWhen using the formatter, only \"double\" is compatible, as the formatter enforces double quotes for docstrings strings.",
|
||||||
"anyOf": [
|
"anyOf": [
|
||||||
{
|
{
|
||||||
"$ref": "#/definitions/Quote"
|
"$ref": "#/definitions/Quote"
|
||||||
|
@ -1094,7 +1094,7 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"inline-quotes": {
|
"inline-quotes": {
|
||||||
"description": "Quote style to prefer for inline strings (either \"single\" or \"double\").",
|
"description": "Quote style to prefer for inline strings (either \"single\" or \"double\").\n\nWhen using the formatter, ensure that `format.quote-style` is set to the same preferred quote style.",
|
||||||
"anyOf": [
|
"anyOf": [
|
||||||
{
|
{
|
||||||
"$ref": "#/definitions/Quote"
|
"$ref": "#/definitions/Quote"
|
||||||
|
@ -1105,7 +1105,7 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"multiline-quotes": {
|
"multiline-quotes": {
|
||||||
"description": "Quote style to prefer for multiline strings (either \"single\" or \"double\").",
|
"description": "Quote style to prefer for multiline strings (either \"single\" or \"double\").\n\nWhen using the formatter, only \"double\" is compatible, as the formatter enforces double quotes for multiline strings.",
|
||||||
"anyOf": [
|
"anyOf": [
|
||||||
{
|
{
|
||||||
"$ref": "#/definitions/Quote"
|
"$ref": "#/definitions/Quote"
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue