mirror of https://github.com/astral-sh/ruff
Allow implicit multiline strings with internal quotes to use non-preferred quote (#2416)
As an example, if you have `single` as your preferred style, we'll now allow this:
```py
assert s.to_python(123) == (
"123 info=SerializationInfo(include=None, exclude=None, mode='python', by_alias=True, exclude_unset=False, "
"exclude_defaults=False, exclude_none=False, round_trip=False)"
)
```
Previously, the second line of the implicit string concatenation would be flagged as invalid, despite the _first_ line requiring double quotes. (Note that we'll accept either single or double quotes for that second line.)
Mechanically, this required that we process sequences of `Tok::String` rather than a single `Tok::String` at a time. Prior to iterating over the strings in the sequence, we check if any of them require the non-preferred quote style; if so, we let _any_ of them use it.
Closes #2400.
This commit is contained in:
parent
1dd9ccf7f6
commit
fbf231e1b8
|
|
@ -1,2 +1,4 @@
|
|||
this_should_be_linted = "double quote string"
|
||||
this_should_be_linted = u"double quote string"
|
||||
this_should_be_linted = f"double quote string"
|
||||
this_should_be_linted = f"double {'quote'} string"
|
||||
|
|
|
|||
|
|
@ -4,3 +4,8 @@ this_is_fine = '"This" is a \'string\''
|
|||
this_is_fine = "This is a 'string'"
|
||||
this_is_fine = "\"This\" is a 'string'"
|
||||
this_is_fine = r'This is a \'string\''
|
||||
this_is_fine = R'This is a \'string\''
|
||||
this_should_raise = (
|
||||
'This is a'
|
||||
'\'string\''
|
||||
)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,27 @@
|
|||
x = (
|
||||
"This"
|
||||
"is"
|
||||
"not"
|
||||
)
|
||||
|
||||
x = (
|
||||
"This" \
|
||||
"is" \
|
||||
"not"
|
||||
)
|
||||
|
||||
x = (
|
||||
"This"
|
||||
"is 'actually'"
|
||||
"fine"
|
||||
)
|
||||
|
||||
x = (
|
||||
"This" \
|
||||
"is 'actually'" \
|
||||
"fine"
|
||||
)
|
||||
|
||||
if True:
|
||||
"This can use 'double' quotes"
|
||||
"But this needs to be changed"
|
||||
|
|
@ -1,2 +1,4 @@
|
|||
this_should_be_linted = 'single quote string'
|
||||
this_should_be_linted = u'double quote string'
|
||||
this_should_be_linted = f'double quote string'
|
||||
this_should_be_linted = f'double {"quote"} string'
|
||||
|
|
|
|||
|
|
@ -3,3 +3,8 @@ this_is_fine = "'This' is a \"string\""
|
|||
this_is_fine = 'This is a "string"'
|
||||
this_is_fine = '\'This\' is a "string"'
|
||||
this_is_fine = r"This is a \"string\""
|
||||
this_is_fine = R"This is a \"string\""
|
||||
this_should_raise = (
|
||||
"This is a"
|
||||
"\"string\""
|
||||
)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,27 @@
|
|||
x = (
|
||||
'This'
|
||||
'is'
|
||||
'not'
|
||||
)
|
||||
|
||||
x = (
|
||||
'This' \
|
||||
'is' \
|
||||
'not'
|
||||
)
|
||||
|
||||
x = (
|
||||
'This'
|
||||
'is "actually"'
|
||||
'fine'
|
||||
)
|
||||
|
||||
x = (
|
||||
'This' \
|
||||
'is "actually"' \
|
||||
'fine'
|
||||
)
|
||||
|
||||
if True:
|
||||
'This can use "single" quotes'
|
||||
'But this needs to be changed'
|
||||
|
|
@ -48,9 +48,13 @@ pub fn check_tokens(
|
|||
|| settings.rules.enabled(&Rule::TrailingCommaProhibited);
|
||||
let enforce_extraneous_parenthesis = settings.rules.enabled(&Rule::ExtraneousParentheses);
|
||||
|
||||
if enforce_ambiguous_unicode_character
|
||||
|| enforce_commented_out_code
|
||||
|| enforce_invalid_escape_sequence
|
||||
{
|
||||
let mut state_machine = StateMachine::default();
|
||||
for &(start, ref tok, end) in tokens.iter().flatten() {
|
||||
let is_docstring = if enforce_ambiguous_unicode_character || enforce_quotes {
|
||||
let is_docstring = if enforce_ambiguous_unicode_character {
|
||||
state_machine.consume(tok)
|
||||
} else {
|
||||
false
|
||||
|
|
@ -78,24 +82,6 @@ pub fn check_tokens(
|
|||
}
|
||||
}
|
||||
|
||||
// flake8-quotes
|
||||
if enforce_quotes {
|
||||
if matches!(tok, Tok::String { .. }) {
|
||||
if let Some(diagnostic) = flake8_quotes::rules::quotes(
|
||||
locator,
|
||||
start,
|
||||
end,
|
||||
is_docstring,
|
||||
settings,
|
||||
autofix,
|
||||
) {
|
||||
if settings.rules.enabled(diagnostic.kind.rule()) {
|
||||
diagnostics.push(diagnostic);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// eradicate
|
||||
if enforce_commented_out_code {
|
||||
if matches!(tok, Tok::Comment(_)) {
|
||||
|
|
@ -120,6 +106,16 @@ pub fn check_tokens(
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Q001, Q002, Q003
|
||||
if enforce_quotes {
|
||||
diagnostics.extend(
|
||||
flake8_quotes::rules::from_tokens(tokens, locator, settings, autofix)
|
||||
.into_iter()
|
||||
.filter(|diagnostic| settings.rules.enabled(diagnostic.kind.rule())),
|
||||
);
|
||||
}
|
||||
|
||||
// ISC001, ISC002
|
||||
if enforce_implicit_string_concatenation {
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ mod tests {
|
|||
|
||||
#[test_case(Path::new("doubles.py"))]
|
||||
#[test_case(Path::new("doubles_escaped.py"))]
|
||||
#[test_case(Path::new("doubles_implicit.py"))]
|
||||
#[test_case(Path::new("doubles_multiline_string.py"))]
|
||||
#[test_case(Path::new("doubles_noqa.py"))]
|
||||
#[test_case(Path::new("doubles_wrapped.py"))]
|
||||
|
|
@ -47,6 +48,7 @@ mod tests {
|
|||
|
||||
#[test_case(Path::new("singles.py"))]
|
||||
#[test_case(Path::new("singles_escaped.py"))]
|
||||
#[test_case(Path::new("singles_implicit.py"))]
|
||||
#[test_case(Path::new("singles_multiline_string.py"))]
|
||||
#[test_case(Path::new("singles_noqa.py"))]
|
||||
#[test_case(Path::new("singles_wrapped.py"))]
|
||||
|
|
|
|||
|
|
@ -1,13 +1,16 @@
|
|||
use rustpython_ast::Location;
|
||||
use rustpython_parser::lexer::{LexResult, Tok};
|
||||
|
||||
use super::settings::Quote;
|
||||
use crate::ast::types::Range;
|
||||
use crate::fix::Fix;
|
||||
use crate::lex::docstring_detection::StateMachine;
|
||||
use crate::registry::{Diagnostic, Rule};
|
||||
use crate::settings::{flags, Settings};
|
||||
use crate::source_code::Locator;
|
||||
use crate::violations;
|
||||
|
||||
use super::settings::Quote;
|
||||
|
||||
fn good_single(quote: &Quote) -> char {
|
||||
match quote {
|
||||
Quote::Single => '\'',
|
||||
|
|
@ -43,22 +46,20 @@ fn good_docstring(quote: &Quote) -> &str {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn quotes(
|
||||
locator: &Locator,
|
||||
start: Location,
|
||||
end: Location,
|
||||
is_docstring: bool,
|
||||
settings: &Settings,
|
||||
autofix: flags::Autofix,
|
||||
) -> Option<Diagnostic> {
|
||||
let quotes_settings = &settings.flake8_quotes;
|
||||
let text = locator.slice_source_code_range(&Range::new(start, end));
|
||||
struct Trivia<'a> {
|
||||
last_quote_char: char,
|
||||
prefix: &'a str,
|
||||
raw_text: &'a str,
|
||||
is_multiline: bool,
|
||||
}
|
||||
|
||||
impl<'a> From<&'a str> for Trivia<'a> {
|
||||
fn from(value: &'a str) -> Self {
|
||||
// Remove any prefixes (e.g., remove `u` from `u"foo"`).
|
||||
let last_quote_char = text.chars().last().unwrap();
|
||||
let first_quote_char = text.find(last_quote_char).unwrap();
|
||||
let prefix = &text[..first_quote_char].to_lowercase();
|
||||
let raw_text = &text[first_quote_char..];
|
||||
let last_quote_char = value.chars().last().unwrap();
|
||||
let first_quote_char = value.find(last_quote_char).unwrap();
|
||||
let prefix = &value[..first_quote_char];
|
||||
let raw_text = &value[first_quote_char..];
|
||||
|
||||
// Determine if the string is multiline-based.
|
||||
let is_multiline = if raw_text.len() >= 3 {
|
||||
|
|
@ -71,8 +72,32 @@ pub fn quotes(
|
|||
false
|
||||
};
|
||||
|
||||
if is_docstring {
|
||||
if raw_text.contains(good_docstring("es_settings.docstring_quotes)) {
|
||||
Self {
|
||||
last_quote_char,
|
||||
prefix,
|
||||
raw_text,
|
||||
is_multiline,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Q003
|
||||
fn docstring(
|
||||
locator: &Locator,
|
||||
start: Location,
|
||||
end: Location,
|
||||
settings: &Settings,
|
||||
autofix: flags::Autofix,
|
||||
) -> Option<Diagnostic> {
|
||||
let quotes_settings = &settings.flake8_quotes;
|
||||
|
||||
let text = locator.slice_source_code_range(&Range::new(start, end));
|
||||
let trivia: Trivia = text.into();
|
||||
|
||||
if trivia
|
||||
.raw_text
|
||||
.contains(good_docstring("es_settings.docstring_quotes))
|
||||
{
|
||||
return None;
|
||||
}
|
||||
|
||||
|
|
@ -85,71 +110,120 @@ pub fn quotes(
|
|||
if matches!(autofix, flags::Autofix::Enabled)
|
||||
&& settings.rules.should_fix(&Rule::BadQuotesDocstring)
|
||||
{
|
||||
let quote_count = if is_multiline { 3 } else { 1 };
|
||||
let string_contents = &raw_text[quote_count..raw_text.len() - quote_count];
|
||||
let quote_count = if trivia.is_multiline { 3 } else { 1 };
|
||||
let string_contents = &trivia.raw_text[quote_count..trivia.raw_text.len() - quote_count];
|
||||
let quote = good_docstring("es_settings.docstring_quotes).repeat(quote_count);
|
||||
let mut fixed_contents =
|
||||
String::with_capacity(prefix.len() + string_contents.len() + quote.len() * 2);
|
||||
fixed_contents.push_str(prefix);
|
||||
String::with_capacity(trivia.prefix.len() + string_contents.len() + quote.len() * 2);
|
||||
fixed_contents.push_str(trivia.prefix);
|
||||
fixed_contents.push_str("e);
|
||||
fixed_contents.push_str(string_contents);
|
||||
fixed_contents.push_str("e);
|
||||
diagnostic.amend(Fix::replacement(fixed_contents, start, end));
|
||||
}
|
||||
Some(diagnostic)
|
||||
} else if is_multiline {
|
||||
}
|
||||
|
||||
/// Q001, Q002
|
||||
fn strings(
|
||||
locator: &Locator,
|
||||
sequence: &[(Location, Location)],
|
||||
settings: &Settings,
|
||||
autofix: flags::Autofix,
|
||||
) -> Vec<Diagnostic> {
|
||||
let mut diagnostics = vec![];
|
||||
|
||||
let quotes_settings = &settings.flake8_quotes;
|
||||
|
||||
let trivia = sequence
|
||||
.iter()
|
||||
.map(|(start, end)| {
|
||||
let text = locator.slice_source_code_range(&Range::new(*start, *end));
|
||||
let trivia: Trivia = text.into();
|
||||
trivia
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
// Return `true` if any of the strings are inline strings that contain the quote character in
|
||||
// the body.
|
||||
let relax_quote = trivia.iter().any(|trivia| {
|
||||
if trivia.is_multiline {
|
||||
return false;
|
||||
}
|
||||
|
||||
if trivia.last_quote_char == good_single("es_settings.inline_quotes) {
|
||||
return false;
|
||||
}
|
||||
|
||||
let string_contents = &trivia.raw_text[1..trivia.raw_text.len() - 1];
|
||||
string_contents.contains(good_single("es_settings.inline_quotes))
|
||||
});
|
||||
|
||||
for ((start, end), trivia) in sequence.iter().zip(trivia.into_iter()) {
|
||||
if trivia.is_multiline {
|
||||
// If our string is or contains a known good string, ignore it.
|
||||
if raw_text.contains(good_multiline("es_settings.multiline_quotes)) {
|
||||
return None;
|
||||
if trivia
|
||||
.raw_text
|
||||
.contains(good_multiline("es_settings.multiline_quotes))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// If our string ends with a known good ending, then ignore it.
|
||||
if raw_text.ends_with(good_multiline_ending("es_settings.multiline_quotes)) {
|
||||
return None;
|
||||
if trivia
|
||||
.raw_text
|
||||
.ends_with(good_multiline_ending("es_settings.multiline_quotes))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
let mut diagnostic = Diagnostic::new(
|
||||
violations::BadQuotesMultilineString {
|
||||
quote: quotes_settings.multiline_quotes.clone(),
|
||||
},
|
||||
Range::new(start, end),
|
||||
Range::new(*start, *end),
|
||||
);
|
||||
|
||||
if matches!(autofix, flags::Autofix::Enabled)
|
||||
&& settings.rules.should_fix(&Rule::BadQuotesMultilineString)
|
||||
{
|
||||
let string_contents = &raw_text[3..raw_text.len() - 3];
|
||||
let string_contents = &trivia.raw_text[3..trivia.raw_text.len() - 3];
|
||||
let quote = good_multiline("es_settings.multiline_quotes);
|
||||
let mut fixed_contents =
|
||||
String::with_capacity(prefix.len() + string_contents.len() + quote.len() * 2);
|
||||
fixed_contents.push_str(prefix);
|
||||
let mut fixed_contents = String::with_capacity(
|
||||
trivia.prefix.len() + string_contents.len() + quote.len() * 2,
|
||||
);
|
||||
fixed_contents.push_str(trivia.prefix);
|
||||
fixed_contents.push_str(quote);
|
||||
fixed_contents.push_str(string_contents);
|
||||
fixed_contents.push_str(quote);
|
||||
diagnostic.amend(Fix::replacement(fixed_contents, start, end));
|
||||
diagnostic.amend(Fix::replacement(fixed_contents, *start, *end));
|
||||
}
|
||||
Some(diagnostic)
|
||||
diagnostics.push(diagnostic);
|
||||
} else {
|
||||
let string_contents = &raw_text[1..raw_text.len() - 1];
|
||||
let string_contents = &trivia.raw_text[1..trivia.raw_text.len() - 1];
|
||||
|
||||
// If we're using the preferred quotation type, check for escapes.
|
||||
if last_quote_char == good_single("es_settings.inline_quotes) {
|
||||
if !quotes_settings.avoid_escape || prefix.contains('r') {
|
||||
return None;
|
||||
if trivia.last_quote_char == good_single("es_settings.inline_quotes) {
|
||||
if !quotes_settings.avoid_escape
|
||||
|| trivia.prefix.contains('r')
|
||||
|| trivia.prefix.contains('R')
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if string_contents.contains(good_single("es_settings.inline_quotes))
|
||||
&& !string_contents.contains(bad_single("es_settings.inline_quotes))
|
||||
{
|
||||
let mut diagnostic =
|
||||
Diagnostic::new(violations::AvoidQuoteEscape, Range::new(start, end));
|
||||
Diagnostic::new(violations::AvoidQuoteEscape, Range::new(*start, *end));
|
||||
if matches!(autofix, flags::Autofix::Enabled)
|
||||
&& settings.rules.should_fix(&Rule::AvoidQuoteEscape)
|
||||
{
|
||||
let quote = bad_single("es_settings.inline_quotes);
|
||||
|
||||
let mut fixed_contents =
|
||||
String::with_capacity(prefix.len() + string_contents.len() + 2);
|
||||
fixed_contents.push_str(prefix);
|
||||
String::with_capacity(trivia.prefix.len() + string_contents.len() + 2);
|
||||
fixed_contents.push_str(trivia.prefix);
|
||||
fixed_contents.push(quote);
|
||||
|
||||
let chars: Vec<char> = string_contents.chars().collect();
|
||||
|
|
@ -162,7 +236,10 @@ pub fn quotes(
|
|||
}
|
||||
backslash_count += 1;
|
||||
// If the previous character was also a backslash
|
||||
if col_offset > 0 && chars[col_offset - 1] == '\\' && backslash_count == 2 {
|
||||
if col_offset > 0
|
||||
&& chars[col_offset - 1] == '\\'
|
||||
&& backslash_count == 2
|
||||
{
|
||||
fixed_contents.push(char);
|
||||
// reset to 0
|
||||
backslash_count = 0;
|
||||
|
|
@ -185,36 +262,86 @@ pub fn quotes(
|
|||
|
||||
fixed_contents.push(quote);
|
||||
|
||||
diagnostic.amend(Fix::replacement(fixed_contents, start, end));
|
||||
diagnostic.amend(Fix::replacement(fixed_contents, *start, *end));
|
||||
}
|
||||
return Some(diagnostic);
|
||||
diagnostics.push(diagnostic);
|
||||
}
|
||||
return None;
|
||||
continue;
|
||||
}
|
||||
|
||||
// If we're not using the preferred type, only allow use to avoid escapes.
|
||||
if !string_contents.contains(good_single("es_settings.inline_quotes)) {
|
||||
if !relax_quote {
|
||||
let mut diagnostic = Diagnostic::new(
|
||||
violations::BadQuotesInlineString {
|
||||
quote: quotes_settings.inline_quotes.clone(),
|
||||
},
|
||||
Range::new(start, end),
|
||||
Range::new(*start, *end),
|
||||
);
|
||||
if matches!(autofix, flags::Autofix::Enabled)
|
||||
&& settings.rules.should_fix(&Rule::BadQuotesInlineString)
|
||||
{
|
||||
let quote = good_single("es_settings.inline_quotes);
|
||||
let mut fixed_contents =
|
||||
String::with_capacity(prefix.len() + string_contents.len() + 2);
|
||||
fixed_contents.push_str(prefix);
|
||||
String::with_capacity(trivia.prefix.len() + string_contents.len() + 2);
|
||||
fixed_contents.push_str(trivia.prefix);
|
||||
fixed_contents.push(quote);
|
||||
fixed_contents.push_str(string_contents);
|
||||
fixed_contents.push(quote);
|
||||
diagnostic.amend(Fix::replacement(fixed_contents, start, end));
|
||||
diagnostic.amend(Fix::replacement(fixed_contents, *start, *end));
|
||||
}
|
||||
diagnostics.push(diagnostic);
|
||||
}
|
||||
}
|
||||
return Some(diagnostic);
|
||||
}
|
||||
|
||||
None
|
||||
diagnostics
|
||||
}
|
||||
|
||||
/// Generate `flake8-quote` diagnostics from a token stream.
|
||||
pub fn from_tokens(
|
||||
lxr: &[LexResult],
|
||||
locator: &Locator,
|
||||
settings: &Settings,
|
||||
autofix: flags::Autofix,
|
||||
) -> Vec<Diagnostic> {
|
||||
let mut diagnostics = vec![];
|
||||
|
||||
// Keep track of sequences of strings, which represent implicit string concatenation, and
|
||||
// should thus be handled as a single unit.
|
||||
let mut sequence = vec![];
|
||||
let mut state_machine = StateMachine::default();
|
||||
for &(start, ref tok, end) in lxr.iter().flatten() {
|
||||
let is_docstring = state_machine.consume(tok);
|
||||
|
||||
// If this is a docstring, consume the existing sequence, then consume the docstring, then
|
||||
// move on.
|
||||
if is_docstring {
|
||||
if !sequence.is_empty() {
|
||||
diagnostics.extend(strings(locator, &sequence, settings, autofix));
|
||||
sequence.clear();
|
||||
}
|
||||
if let Some(diagnostic) = docstring(locator, start, end, settings, autofix) {
|
||||
diagnostics.push(diagnostic);
|
||||
}
|
||||
} else {
|
||||
if matches!(tok, Tok::String { .. }) {
|
||||
// If this is a string, add it to the sequence.
|
||||
sequence.push((start, end));
|
||||
} else if !matches!(tok, Tok::Comment(..) | Tok::NonLogicalNewline) {
|
||||
// Otherwise, consume the sequence.
|
||||
if !sequence.is_empty() {
|
||||
diagnostics.extend(strings(locator, &sequence, settings, autofix));
|
||||
sequence.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If we have an unterminated sequence, consume it.
|
||||
if !sequence.is_empty() {
|
||||
diagnostics.extend(strings(locator, &sequence, settings, autofix));
|
||||
sequence.clear();
|
||||
}
|
||||
|
||||
diagnostics
|
||||
}
|
||||
|
|
|
|||
|
|
@ -40,4 +40,23 @@ expression: diagnostics
|
|||
row: 2
|
||||
column: 46
|
||||
parent: ~
|
||||
- kind:
|
||||
BadQuotesInlineString:
|
||||
quote: double
|
||||
location:
|
||||
row: 3
|
||||
column: 24
|
||||
end_location:
|
||||
row: 3
|
||||
column: 46
|
||||
fix:
|
||||
content:
|
||||
- "f\"double quote string\""
|
||||
location:
|
||||
row: 3
|
||||
column: 24
|
||||
end_location:
|
||||
row: 3
|
||||
column: 46
|
||||
parent: ~
|
||||
|
||||
|
|
|
|||
|
|
@ -20,4 +20,22 @@ expression: diagnostics
|
|||
row: 1
|
||||
column: 47
|
||||
parent: ~
|
||||
- kind:
|
||||
AvoidQuoteEscape: ~
|
||||
location:
|
||||
row: 9
|
||||
column: 4
|
||||
end_location:
|
||||
row: 9
|
||||
column: 16
|
||||
fix:
|
||||
content:
|
||||
- "'\"string\"'"
|
||||
location:
|
||||
row: 9
|
||||
column: 4
|
||||
end_location:
|
||||
row: 9
|
||||
column: 16
|
||||
parent: ~
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,138 @@
|
|||
---
|
||||
source: src/rules/flake8_quotes/mod.rs
|
||||
expression: diagnostics
|
||||
---
|
||||
- kind:
|
||||
BadQuotesInlineString:
|
||||
quote: double
|
||||
location:
|
||||
row: 2
|
||||
column: 4
|
||||
end_location:
|
||||
row: 2
|
||||
column: 10
|
||||
fix:
|
||||
content:
|
||||
- "\"This\""
|
||||
location:
|
||||
row: 2
|
||||
column: 4
|
||||
end_location:
|
||||
row: 2
|
||||
column: 10
|
||||
parent: ~
|
||||
- kind:
|
||||
BadQuotesInlineString:
|
||||
quote: double
|
||||
location:
|
||||
row: 3
|
||||
column: 4
|
||||
end_location:
|
||||
row: 3
|
||||
column: 8
|
||||
fix:
|
||||
content:
|
||||
- "\"is\""
|
||||
location:
|
||||
row: 3
|
||||
column: 4
|
||||
end_location:
|
||||
row: 3
|
||||
column: 8
|
||||
parent: ~
|
||||
- kind:
|
||||
BadQuotesInlineString:
|
||||
quote: double
|
||||
location:
|
||||
row: 4
|
||||
column: 4
|
||||
end_location:
|
||||
row: 4
|
||||
column: 9
|
||||
fix:
|
||||
content:
|
||||
- "\"not\""
|
||||
location:
|
||||
row: 4
|
||||
column: 4
|
||||
end_location:
|
||||
row: 4
|
||||
column: 9
|
||||
parent: ~
|
||||
- kind:
|
||||
BadQuotesInlineString:
|
||||
quote: double
|
||||
location:
|
||||
row: 8
|
||||
column: 4
|
||||
end_location:
|
||||
row: 8
|
||||
column: 10
|
||||
fix:
|
||||
content:
|
||||
- "\"This\""
|
||||
location:
|
||||
row: 8
|
||||
column: 4
|
||||
end_location:
|
||||
row: 8
|
||||
column: 10
|
||||
parent: ~
|
||||
- kind:
|
||||
BadQuotesInlineString:
|
||||
quote: double
|
||||
location:
|
||||
row: 9
|
||||
column: 4
|
||||
end_location:
|
||||
row: 9
|
||||
column: 8
|
||||
fix:
|
||||
content:
|
||||
- "\"is\""
|
||||
location:
|
||||
row: 9
|
||||
column: 4
|
||||
end_location:
|
||||
row: 9
|
||||
column: 8
|
||||
parent: ~
|
||||
- kind:
|
||||
BadQuotesInlineString:
|
||||
quote: double
|
||||
location:
|
||||
row: 10
|
||||
column: 4
|
||||
end_location:
|
||||
row: 10
|
||||
column: 9
|
||||
fix:
|
||||
content:
|
||||
- "\"not\""
|
||||
location:
|
||||
row: 10
|
||||
column: 4
|
||||
end_location:
|
||||
row: 10
|
||||
column: 9
|
||||
parent: ~
|
||||
- kind:
|
||||
BadQuotesInlineString:
|
||||
quote: double
|
||||
location:
|
||||
row: 27
|
||||
column: 0
|
||||
end_location:
|
||||
row: 27
|
||||
column: 30
|
||||
fix:
|
||||
content:
|
||||
- "\"But this needs to be changed\""
|
||||
location:
|
||||
row: 27
|
||||
column: 0
|
||||
end_location:
|
||||
row: 27
|
||||
column: 30
|
||||
parent: ~
|
||||
|
||||
|
|
@ -40,4 +40,23 @@ expression: diagnostics
|
|||
row: 2
|
||||
column: 46
|
||||
parent: ~
|
||||
- kind:
|
||||
BadQuotesInlineString:
|
||||
quote: single
|
||||
location:
|
||||
row: 3
|
||||
column: 24
|
||||
end_location:
|
||||
row: 3
|
||||
column: 46
|
||||
fix:
|
||||
content:
|
||||
- "f'double quote string'"
|
||||
location:
|
||||
row: 3
|
||||
column: 24
|
||||
end_location:
|
||||
row: 3
|
||||
column: 46
|
||||
parent: ~
|
||||
|
||||
|
|
|
|||
|
|
@ -38,4 +38,22 @@ expression: diagnostics
|
|||
row: 2
|
||||
column: 52
|
||||
parent: ~
|
||||
- kind:
|
||||
AvoidQuoteEscape: ~
|
||||
location:
|
||||
row: 10
|
||||
column: 4
|
||||
end_location:
|
||||
row: 10
|
||||
column: 16
|
||||
fix:
|
||||
content:
|
||||
- "\"'string'\""
|
||||
location:
|
||||
row: 10
|
||||
column: 4
|
||||
end_location:
|
||||
row: 10
|
||||
column: 16
|
||||
parent: ~
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,138 @@
|
|||
---
|
||||
source: src/rules/flake8_quotes/mod.rs
|
||||
expression: diagnostics
|
||||
---
|
||||
- kind:
|
||||
BadQuotesInlineString:
|
||||
quote: single
|
||||
location:
|
||||
row: 2
|
||||
column: 4
|
||||
end_location:
|
||||
row: 2
|
||||
column: 10
|
||||
fix:
|
||||
content:
|
||||
- "'This'"
|
||||
location:
|
||||
row: 2
|
||||
column: 4
|
||||
end_location:
|
||||
row: 2
|
||||
column: 10
|
||||
parent: ~
|
||||
- kind:
|
||||
BadQuotesInlineString:
|
||||
quote: single
|
||||
location:
|
||||
row: 3
|
||||
column: 4
|
||||
end_location:
|
||||
row: 3
|
||||
column: 8
|
||||
fix:
|
||||
content:
|
||||
- "'is'"
|
||||
location:
|
||||
row: 3
|
||||
column: 4
|
||||
end_location:
|
||||
row: 3
|
||||
column: 8
|
||||
parent: ~
|
||||
- kind:
|
||||
BadQuotesInlineString:
|
||||
quote: single
|
||||
location:
|
||||
row: 4
|
||||
column: 4
|
||||
end_location:
|
||||
row: 4
|
||||
column: 9
|
||||
fix:
|
||||
content:
|
||||
- "'not'"
|
||||
location:
|
||||
row: 4
|
||||
column: 4
|
||||
end_location:
|
||||
row: 4
|
||||
column: 9
|
||||
parent: ~
|
||||
- kind:
|
||||
BadQuotesInlineString:
|
||||
quote: single
|
||||
location:
|
||||
row: 8
|
||||
column: 4
|
||||
end_location:
|
||||
row: 8
|
||||
column: 10
|
||||
fix:
|
||||
content:
|
||||
- "'This'"
|
||||
location:
|
||||
row: 8
|
||||
column: 4
|
||||
end_location:
|
||||
row: 8
|
||||
column: 10
|
||||
parent: ~
|
||||
- kind:
|
||||
BadQuotesInlineString:
|
||||
quote: single
|
||||
location:
|
||||
row: 9
|
||||
column: 4
|
||||
end_location:
|
||||
row: 9
|
||||
column: 8
|
||||
fix:
|
||||
content:
|
||||
- "'is'"
|
||||
location:
|
||||
row: 9
|
||||
column: 4
|
||||
end_location:
|
||||
row: 9
|
||||
column: 8
|
||||
parent: ~
|
||||
- kind:
|
||||
BadQuotesInlineString:
|
||||
quote: single
|
||||
location:
|
||||
row: 10
|
||||
column: 4
|
||||
end_location:
|
||||
row: 10
|
||||
column: 9
|
||||
fix:
|
||||
content:
|
||||
- "'not'"
|
||||
location:
|
||||
row: 10
|
||||
column: 4
|
||||
end_location:
|
||||
row: 10
|
||||
column: 9
|
||||
parent: ~
|
||||
- kind:
|
||||
BadQuotesInlineString:
|
||||
quote: single
|
||||
location:
|
||||
row: 27
|
||||
column: 0
|
||||
end_location:
|
||||
row: 27
|
||||
column: 30
|
||||
fix:
|
||||
content:
|
||||
- "'But this needs to be changed'"
|
||||
location:
|
||||
row: 27
|
||||
column: 0
|
||||
end_location:
|
||||
row: 27
|
||||
column: 30
|
||||
parent: ~
|
||||
|
||||
Loading…
Reference in New Issue