From cdaf1df2752263221d03ac61b3f048a956e61a1e Mon Sep 17 00:00:00 2001 From: Charlie Marsh Date: Mon, 1 Apr 2024 23:00:44 -0400 Subject: [PATCH] Respect Q00* ignores in flake8-quotes rules --- .../fixtures/flake8_quotes/doubles_all.py | 7 +++ .../src/rules/flake8_quotes/mod.rs | 57 +++++++++++++++++++ .../rules/check_string_quotes.rs | 21 ++++++- ..._tests__only_docstring_doubles_all.py.snap | 18 ++++++ ...es__tests__only_inline_doubles_all.py.snap | 22 +++++++ ..._tests__only_multiline_doubles_all.py.snap | 24 ++++++++ 6 files changed, 146 insertions(+), 3 deletions(-) create mode 100644 crates/ruff_linter/resources/test/fixtures/flake8_quotes/doubles_all.py create mode 100644 crates/ruff_linter/src/rules/flake8_quotes/snapshots/ruff_linter__rules__flake8_quotes__tests__only_docstring_doubles_all.py.snap create mode 100644 crates/ruff_linter/src/rules/flake8_quotes/snapshots/ruff_linter__rules__flake8_quotes__tests__only_inline_doubles_all.py.snap create mode 100644 crates/ruff_linter/src/rules/flake8_quotes/snapshots/ruff_linter__rules__flake8_quotes__tests__only_multiline_doubles_all.py.snap diff --git a/crates/ruff_linter/resources/test/fixtures/flake8_quotes/doubles_all.py b/crates/ruff_linter/resources/test/fixtures/flake8_quotes/doubles_all.py new file mode 100644 index 0000000000000..80c0d8e22c11e --- /dev/null +++ b/crates/ruff_linter/resources/test/fixtures/flake8_quotes/doubles_all.py @@ -0,0 +1,7 @@ +"""This is a docstring.""" + +this_is_an_inline_string = "double quote string" + +this_is_a_multiline_string = """ +double quote string +""" diff --git a/crates/ruff_linter/src/rules/flake8_quotes/mod.rs b/crates/ruff_linter/src/rules/flake8_quotes/mod.rs index 8a69e6c294a51..9025b10e67e55 100644 --- a/crates/ruff_linter/src/rules/flake8_quotes/mod.rs +++ b/crates/ruff_linter/src/rules/flake8_quotes/mod.rs @@ -195,4 +195,61 @@ mod tests { assert_messages!(snapshot, diagnostics); Ok(()) } + + #[test_case(Path::new("doubles_all.py"))] + fn only_inline(path: &Path) -> Result<()> { + let snapshot = format!("only_inline_{}", path.to_string_lossy()); + let diagnostics = test_path( + Path::new("flake8_quotes").join(path).as_path(), + &LinterSettings { + flake8_quotes: super::settings::Settings { + inline_quotes: Quote::Single, + multiline_quotes: Quote::Single, + docstring_quotes: Quote::Single, + avoid_escape: true, + }, + ..LinterSettings::for_rules(vec![Rule::BadQuotesInlineString]) + }, + )?; + assert_messages!(snapshot, diagnostics); + Ok(()) + } + + #[test_case(Path::new("doubles_all.py"))] + fn only_multiline(path: &Path) -> Result<()> { + let snapshot = format!("only_multiline_{}", path.to_string_lossy()); + let diagnostics = test_path( + Path::new("flake8_quotes").join(path).as_path(), + &LinterSettings { + flake8_quotes: super::settings::Settings { + inline_quotes: Quote::Single, + multiline_quotes: Quote::Single, + docstring_quotes: Quote::Single, + avoid_escape: true, + }, + ..LinterSettings::for_rules(vec![Rule::BadQuotesMultilineString]) + }, + )?; + assert_messages!(snapshot, diagnostics); + Ok(()) + } + + #[test_case(Path::new("doubles_all.py"))] + fn only_docstring(path: &Path) -> Result<()> { + let snapshot = format!("only_docstring_{}", path.to_string_lossy()); + let diagnostics = test_path( + Path::new("flake8_quotes").join(path).as_path(), + &LinterSettings { + flake8_quotes: super::settings::Settings { + inline_quotes: Quote::Single, + multiline_quotes: Quote::Single, + docstring_quotes: Quote::Single, + avoid_escape: true, + }, + ..LinterSettings::for_rules(vec![Rule::BadQuotesDocstring]) + }, + )?; + assert_messages!(snapshot, diagnostics); + Ok(()) + } } diff --git a/crates/ruff_linter/src/rules/flake8_quotes/rules/check_string_quotes.rs b/crates/ruff_linter/src/rules/flake8_quotes/rules/check_string_quotes.rs index e5eb47a0dea8c..fc4ff375053ec 100644 --- a/crates/ruff_linter/src/rules/flake8_quotes/rules/check_string_quotes.rs +++ b/crates/ruff_linter/src/rules/flake8_quotes/rules/check_string_quotes.rs @@ -5,6 +5,7 @@ use ruff_source_file::Locator; use ruff_text_size::{Ranged, TextRange}; use crate::checkers::ast::Checker; +use crate::registry::Rule; use super::super::settings::Quote; @@ -334,6 +335,11 @@ fn strings(checker: &mut Checker, sequence: &[TextRange]) { for (range, trivia) in sequence.iter().zip(trivia) { if trivia.is_multiline { + // If multiline strings aren't enforced, ignore it. + if !checker.enabled(Rule::BadQuotesMultilineString) { + continue; + } + // If our string is or contains a known good string, ignore it. if trivia .raw_text @@ -375,6 +381,11 @@ fn strings(checker: &mut Checker, sequence: &[TextRange]) { // If we're not using the preferred type, only allow use to avoid escapes. && !relax_quote { + // If inline strings aren't enforced, ignore it. + if !checker.enabled(Rule::BadQuotesInlineString) { + continue; + } + if trivia.has_empty_text() && text_ends_at_quote(locator, *range, quotes_settings.inline_quotes) { @@ -455,10 +466,14 @@ pub(crate) fn check_string_quotes(checker: &mut Checker, string_like: StringLike }; if checker.semantic().in_docstring() { - for range in ranges { - docstring(checker, range); + if checker.enabled(Rule::BadQuotesDocstring) { + for range in ranges { + docstring(checker, range); + } } } else { - strings(checker, &ranges); + if checker.any_enabled(&[Rule::BadQuotesInlineString, Rule::BadQuotesMultilineString]) { + strings(checker, &ranges); + } } } diff --git a/crates/ruff_linter/src/rules/flake8_quotes/snapshots/ruff_linter__rules__flake8_quotes__tests__only_docstring_doubles_all.py.snap b/crates/ruff_linter/src/rules/flake8_quotes/snapshots/ruff_linter__rules__flake8_quotes__tests__only_docstring_doubles_all.py.snap new file mode 100644 index 0000000000000..6a87062097567 --- /dev/null +++ b/crates/ruff_linter/src/rules/flake8_quotes/snapshots/ruff_linter__rules__flake8_quotes__tests__only_docstring_doubles_all.py.snap @@ -0,0 +1,18 @@ +--- +source: crates/ruff_linter/src/rules/flake8_quotes/mod.rs +--- +doubles_all.py:1:1: Q002 [*] Double quote docstring found but single quotes preferred + | +1 | """This is a docstring.""" + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ Q002 +2 | +3 | this_is_an_inline_string = "double quote string" + | + = help: Replace double quotes docstring with single quotes + +ℹ Safe fix +1 |-"""This is a docstring.""" + 1 |+'''This is a docstring.''' +2 2 | +3 3 | this_is_an_inline_string = "double quote string" +4 4 | diff --git a/crates/ruff_linter/src/rules/flake8_quotes/snapshots/ruff_linter__rules__flake8_quotes__tests__only_inline_doubles_all.py.snap b/crates/ruff_linter/src/rules/flake8_quotes/snapshots/ruff_linter__rules__flake8_quotes__tests__only_inline_doubles_all.py.snap new file mode 100644 index 0000000000000..0ca50ac62e93a --- /dev/null +++ b/crates/ruff_linter/src/rules/flake8_quotes/snapshots/ruff_linter__rules__flake8_quotes__tests__only_inline_doubles_all.py.snap @@ -0,0 +1,22 @@ +--- +source: crates/ruff_linter/src/rules/flake8_quotes/mod.rs +--- +doubles_all.py:3:28: Q000 [*] Double quotes found but single quotes preferred + | +1 | """This is a docstring.""" +2 | +3 | this_is_an_inline_string = "double quote string" + | ^^^^^^^^^^^^^^^^^^^^^ Q000 +4 | +5 | this_is_a_multiline_string = """ + | + = help: Replace double quotes with single quotes + +ℹ Safe fix +1 1 | """This is a docstring.""" +2 2 | +3 |-this_is_an_inline_string = "double quote string" + 3 |+this_is_an_inline_string = 'double quote string' +4 4 | +5 5 | this_is_a_multiline_string = """ +6 6 | double quote string diff --git a/crates/ruff_linter/src/rules/flake8_quotes/snapshots/ruff_linter__rules__flake8_quotes__tests__only_multiline_doubles_all.py.snap b/crates/ruff_linter/src/rules/flake8_quotes/snapshots/ruff_linter__rules__flake8_quotes__tests__only_multiline_doubles_all.py.snap new file mode 100644 index 0000000000000..ddffe1bb80a5f --- /dev/null +++ b/crates/ruff_linter/src/rules/flake8_quotes/snapshots/ruff_linter__rules__flake8_quotes__tests__only_multiline_doubles_all.py.snap @@ -0,0 +1,24 @@ +--- +source: crates/ruff_linter/src/rules/flake8_quotes/mod.rs +--- +doubles_all.py:5:30: Q001 [*] Double quote multiline found but single quotes preferred + | +3 | this_is_an_inline_string = "double quote string" +4 | +5 | this_is_a_multiline_string = """ + | ______________________________^ +6 | | double quote string +7 | | """ + | |___^ Q001 + | + = help: Replace double multiline quotes with single quotes + +ℹ Safe fix +2 2 | +3 3 | this_is_an_inline_string = "double quote string" +4 4 | +5 |-this_is_a_multiline_string = """ + 5 |+this_is_a_multiline_string = ''' +6 6 | double quote string +7 |-""" + 7 |+'''