mirror of https://github.com/astral-sh/ruff
Implement the `flake8-quotes` plugin (#495)
This commit is contained in:
parent
a057c9a323
commit
86265c1d7c
23
README.md
23
README.md
|
|
@ -104,7 +104,17 @@ per-file-ignores = [
|
||||||
]
|
]
|
||||||
```
|
```
|
||||||
|
|
||||||
Alternatively, on the command-line:
|
Plugin configurations should be expressed as subsections, e.g.:
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[tool.ruff]
|
||||||
|
line-length = 88
|
||||||
|
|
||||||
|
[tool.ruff.flake8-quotes]
|
||||||
|
docstring-quotes = "double"
|
||||||
|
```
|
||||||
|
|
||||||
|
Alternatively, common configuration settings can be provided via the command-line:
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
ruff path/to/code/ --select F401 --select F403
|
ruff path/to/code/ --select F401 --select F403
|
||||||
|
|
@ -415,6 +425,15 @@ The 🛠 emoji indicates that a rule is automatically fixable by the `--fix` com
|
||||||
| T201 | PrintFound | `print` found | 🛠 |
|
| T201 | PrintFound | `print` found | 🛠 |
|
||||||
| T203 | PPrintFound | `pprint` found | 🛠 |
|
| T203 | PPrintFound | `pprint` found | 🛠 |
|
||||||
|
|
||||||
|
### flake8-quotes
|
||||||
|
|
||||||
|
| Code | Name | Message | Fix |
|
||||||
|
| ---- | ---- | ------- | --- |
|
||||||
|
| Q000 | BadQuotesInlineString | Single quotes found but double quotes preferred | |
|
||||||
|
| Q001 | BadQuotesMultilineString | Single quote multiline found but double quotes preferred | |
|
||||||
|
| Q002 | BadQuotesDocstring | Single quote docstring found but double quotes preferred | |
|
||||||
|
| Q003 | AvoidQuoteEscape | Change outer quotes to avoid escaping inner quotes | |
|
||||||
|
|
||||||
### Meta rules
|
### Meta rules
|
||||||
|
|
||||||
| Code | Name | Message | Fix |
|
| Code | Name | Message | Fix |
|
||||||
|
|
@ -486,6 +505,7 @@ including:
|
||||||
- [`flake8-builtins`](https://pypi.org/project/flake8-builtins/)
|
- [`flake8-builtins`](https://pypi.org/project/flake8-builtins/)
|
||||||
- [`flake8-super`](https://pypi.org/project/flake8-super/)
|
- [`flake8-super`](https://pypi.org/project/flake8-super/)
|
||||||
- [`flake8-print`](https://pypi.org/project/flake8-print/)
|
- [`flake8-print`](https://pypi.org/project/flake8-print/)
|
||||||
|
- [`flake8-quotes`](https://pypi.org/project/flake8-quotes/)
|
||||||
- [`flake8-comprehensions`](https://pypi.org/project/flake8-comprehensions/)
|
- [`flake8-comprehensions`](https://pypi.org/project/flake8-comprehensions/)
|
||||||
- [`flake8-bugbear`](https://pypi.org/project/flake8-bugbear/) (9/32)
|
- [`flake8-bugbear`](https://pypi.org/project/flake8-bugbear/) (9/32)
|
||||||
- [`pyupgrade`](https://pypi.org/project/pyupgrade/) (8/34)
|
- [`pyupgrade`](https://pypi.org/project/pyupgrade/) (8/34)
|
||||||
|
|
@ -506,6 +526,7 @@ Today, Ruff can be used to replace Flake8 when used with any of the following pl
|
||||||
- [`flake8-builtins`](https://pypi.org/project/flake8-builtins/)
|
- [`flake8-builtins`](https://pypi.org/project/flake8-builtins/)
|
||||||
- [`flake8-super`](https://pypi.org/project/flake8-super/)
|
- [`flake8-super`](https://pypi.org/project/flake8-super/)
|
||||||
- [`flake8-print`](https://pypi.org/project/flake8-print/)
|
- [`flake8-print`](https://pypi.org/project/flake8-print/)
|
||||||
|
- [`flake8-quotes`](https://pypi.org/project/flake8-quotes/)
|
||||||
- [`flake8-comprehensions`](https://pypi.org/project/flake8-comprehensions/)
|
- [`flake8-comprehensions`](https://pypi.org/project/flake8-comprehensions/)
|
||||||
- [`flake8-bugbear`](https://pypi.org/project/flake8-bugbear/) (9/32)
|
- [`flake8-bugbear`](https://pypi.org/project/flake8-bugbear/) (9/32)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,38 @@
|
||||||
|
"""
|
||||||
|
Double quotes multiline module docstring
|
||||||
|
"""
|
||||||
|
|
||||||
|
"""
|
||||||
|
this is not a docstring
|
||||||
|
"""
|
||||||
|
|
||||||
|
l = []
|
||||||
|
|
||||||
|
class Cls:
|
||||||
|
"""
|
||||||
|
Double quotes multiline class docstring
|
||||||
|
"""
|
||||||
|
|
||||||
|
"""
|
||||||
|
this is not a docstring
|
||||||
|
"""
|
||||||
|
|
||||||
|
# The colon in the list indexing below is an edge case for the docstring scanner
|
||||||
|
def f(self, bar="""
|
||||||
|
definitely not a docstring""",
|
||||||
|
val=l[Cls():3]):
|
||||||
|
"""
|
||||||
|
Double quotes multiline function docstring
|
||||||
|
"""
|
||||||
|
|
||||||
|
some_expression = 'hello world'
|
||||||
|
|
||||||
|
"""
|
||||||
|
this is not a docstring
|
||||||
|
"""
|
||||||
|
|
||||||
|
if l:
|
||||||
|
"""
|
||||||
|
Looks like a docstring, but in reality it isn't - only modules, classes and functions
|
||||||
|
"""
|
||||||
|
pass
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
class SingleLineDocstrings():
|
||||||
|
""" Double quotes single line class docstring """
|
||||||
|
""" Not a docstring """
|
||||||
|
|
||||||
|
def foo(self, bar="""not a docstring"""):
|
||||||
|
""" Double quotes single line method docstring"""
|
||||||
|
pass
|
||||||
|
|
||||||
|
class Nested(foo()[:]): """ inline docstring """; pass
|
||||||
|
|
@ -0,0 +1,22 @@
|
||||||
|
def foo():
|
||||||
|
"""function without params, single line docstring"""
|
||||||
|
""" not a docstring"""
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
|
def foo2():
|
||||||
|
"""
|
||||||
|
function without params, multiline docstring
|
||||||
|
"""
|
||||||
|
""" not a docstring"""
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
|
def fun_with_params_no_docstring(a, b="""
|
||||||
|
not a
|
||||||
|
""" """docstring"""):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def fun_with_params_no_docstring2(a, b=c[foo():], c=\
|
||||||
|
""" not a docstring """):
|
||||||
|
pass
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
"""
|
||||||
|
Double quotes multiline module docstring
|
||||||
|
"""
|
||||||
|
"""
|
||||||
|
this is not a docstring
|
||||||
|
"""
|
||||||
|
def foo():
|
||||||
|
pass
|
||||||
|
"""
|
||||||
|
this is not a docstring
|
||||||
|
"""
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
""" Double quotes singleline module docstring """
|
||||||
|
""" this is not a docstring """
|
||||||
|
|
||||||
|
def foo():
|
||||||
|
pass
|
||||||
|
""" this is not a docstring """
|
||||||
|
|
@ -0,0 +1,40 @@
|
||||||
|
'''
|
||||||
|
Single quotes multiline module docstring
|
||||||
|
'''
|
||||||
|
|
||||||
|
'''
|
||||||
|
this is not a docstring
|
||||||
|
'''
|
||||||
|
|
||||||
|
l = []
|
||||||
|
|
||||||
|
class Cls(MakeKlass('''
|
||||||
|
class params \t not a docstring
|
||||||
|
''')):
|
||||||
|
'''
|
||||||
|
Single quotes multiline class docstring
|
||||||
|
'''
|
||||||
|
|
||||||
|
'''
|
||||||
|
this is not a docstring
|
||||||
|
'''
|
||||||
|
|
||||||
|
# The colon in the list indexing below is an edge case for the docstring scanner
|
||||||
|
def f(self, bar='''
|
||||||
|
definitely not a docstring''',
|
||||||
|
val=l[Cls():3]):
|
||||||
|
'''
|
||||||
|
Single quotes multiline function docstring
|
||||||
|
'''
|
||||||
|
|
||||||
|
some_expression = 'hello world'
|
||||||
|
|
||||||
|
'''
|
||||||
|
this is not a docstring
|
||||||
|
'''
|
||||||
|
|
||||||
|
if l:
|
||||||
|
'''
|
||||||
|
Looks like a docstring, but in reality it isn't - only modules, classes and functions
|
||||||
|
'''
|
||||||
|
pass
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
class SingleLineDocstrings():
|
||||||
|
''' Double quotes single line class docstring '''
|
||||||
|
''' Not a docstring '''
|
||||||
|
|
||||||
|
def foo(self, bar='''not a docstring'''):
|
||||||
|
''' Double quotes single line method docstring'''
|
||||||
|
pass
|
||||||
|
|
||||||
|
class Nested(foo()[:]): ''' inline docstring '''; pass
|
||||||
|
|
@ -0,0 +1,23 @@
|
||||||
|
def foo():
|
||||||
|
'''function without params, single line docstring'''
|
||||||
|
''' not a docstring'''
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
|
def foo2():
|
||||||
|
'''
|
||||||
|
function without params, multiline docstring
|
||||||
|
'''
|
||||||
|
''' not a docstring'''
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
|
def fun_with_params_no_docstring(a, b='''
|
||||||
|
not a
|
||||||
|
''' '''docstring'''):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def fun_with_params_no_docstring2(a, b=c[foo():], c=\
|
||||||
|
''' not a docstring '''):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
'''
|
||||||
|
Double quotes multiline module docstring
|
||||||
|
'''
|
||||||
|
'''
|
||||||
|
this is not a docstring
|
||||||
|
'''
|
||||||
|
def foo():
|
||||||
|
pass
|
||||||
|
'''
|
||||||
|
this is not a docstring
|
||||||
|
'''
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
''' Double quotes singleline module docstring '''
|
||||||
|
''' this is not a docstring '''
|
||||||
|
|
||||||
|
def foo():
|
||||||
|
pass
|
||||||
|
''' this is not a docstring '''
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
this_should_be_linted = "double quote string"
|
||||||
|
this_should_be_linted = u"double quote string"
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
this_should_raise_Q003 = 'This is a \'string\''
|
||||||
|
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\''
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
s = """ This "should"
|
||||||
|
be
|
||||||
|
"linted" """
|
||||||
|
|
||||||
|
s = ''' This "should"
|
||||||
|
"not" be
|
||||||
|
"linted" '''
|
||||||
|
|
||||||
|
s = """'This should not be linted due to having would-be quadruple end quote'"""
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
this_should_not_be_linted = "double quote string" # noqa
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
s = 'double "quotes" wrapped in singles are ignored'
|
||||||
|
s = "single 'quotes' wrapped in doubles are ignored"
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
this_should_be_linted = 'single quote string'
|
||||||
|
this_should_be_linted = u'double quote string'
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
this_should_raise_Q003 = "This is a \"string\""
|
||||||
|
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\""
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
s = ''' This 'should'
|
||||||
|
be
|
||||||
|
'linted' '''
|
||||||
|
|
||||||
|
s = """ This 'should'
|
||||||
|
'not' be
|
||||||
|
'linted' """
|
||||||
|
|
||||||
|
s = '''"This should not be linted due to having would-be quadruple end quote"'''
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
this_should_not_be_linted = 'single quote string' # noqa
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
s = "single 'quotes' wrapped in doubles are ignored"
|
||||||
|
s = 'double "quotes" wrapped in singles are ignored'
|
||||||
|
|
@ -8,3 +8,9 @@ extend-exclude = [
|
||||||
per-file-ignores = [
|
per-file-ignores = [
|
||||||
"__init__.py:F401",
|
"__init__.py:F401",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[tool.ruff.flake8-quotes]
|
||||||
|
inline-quotes = "single"
|
||||||
|
multiline-quotes = "double"
|
||||||
|
docstring-quotes = "double"
|
||||||
|
avoid-escape = true
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,8 @@ use rustpython_parser::lexer::{LexResult, Tok};
|
||||||
|
|
||||||
use crate::ast::operations::SourceCodeLocator;
|
use crate::ast::operations::SourceCodeLocator;
|
||||||
use crate::checks::{Check, CheckCode};
|
use crate::checks::{Check, CheckCode};
|
||||||
use crate::{pycodestyle, Settings};
|
use crate::flake8_quotes::docstring_detection::StateMachine;
|
||||||
|
use crate::{flake8_quotes, pycodestyle, Settings};
|
||||||
|
|
||||||
pub fn check_tokens(
|
pub fn check_tokens(
|
||||||
checks: &mut Vec<Check>,
|
checks: &mut Vec<Check>,
|
||||||
|
|
@ -12,10 +13,18 @@ pub fn check_tokens(
|
||||||
tokens: &[LexResult],
|
tokens: &[LexResult],
|
||||||
settings: &Settings,
|
settings: &Settings,
|
||||||
) {
|
) {
|
||||||
|
let enforce_invalid_escape_sequence = settings.enabled.contains(&CheckCode::W605);
|
||||||
|
let enforce_quotes = settings.enabled.contains(&CheckCode::Q000)
|
||||||
|
| settings.enabled.contains(&CheckCode::Q001)
|
||||||
|
| settings.enabled.contains(&CheckCode::Q002)
|
||||||
|
| settings.enabled.contains(&CheckCode::Q003);
|
||||||
|
|
||||||
// TODO(charlie): Use a shared SourceCodeLocator between this site and the AST traversal.
|
// TODO(charlie): Use a shared SourceCodeLocator between this site and the AST traversal.
|
||||||
let locator = SourceCodeLocator::new(contents);
|
let locator = SourceCodeLocator::new(contents);
|
||||||
let enforce_invalid_escape_sequence = settings.enabled.contains(&CheckCode::W605);
|
|
||||||
|
let mut state_machine = StateMachine::new();
|
||||||
for (start, tok, end) in tokens.iter().flatten() {
|
for (start, tok, end) in tokens.iter().flatten() {
|
||||||
|
// W605
|
||||||
if enforce_invalid_escape_sequence {
|
if enforce_invalid_escape_sequence {
|
||||||
if matches!(tok, Tok::String { .. }) {
|
if matches!(tok, Tok::String { .. }) {
|
||||||
checks.extend(pycodestyle::checks::invalid_escape_sequence(
|
checks.extend(pycodestyle::checks::invalid_escape_sequence(
|
||||||
|
|
@ -23,5 +32,23 @@ pub fn check_tokens(
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// flake8-quotes
|
||||||
|
if enforce_quotes {
|
||||||
|
let is_docstring = state_machine.consume(tok);
|
||||||
|
if matches!(tok, Tok::String { .. }) {
|
||||||
|
if let Some(check) = flake8_quotes::checks::quotes(
|
||||||
|
&locator,
|
||||||
|
start,
|
||||||
|
end,
|
||||||
|
is_docstring,
|
||||||
|
&settings.flake8_quotes,
|
||||||
|
) {
|
||||||
|
if settings.enabled.contains(check.kind.code()) {
|
||||||
|
checks.push(check);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ use strum_macros::{AsRefStr, EnumIter, EnumString};
|
||||||
|
|
||||||
use crate::ast::types::Range;
|
use crate::ast::types::Range;
|
||||||
use crate::autofix::Fix;
|
use crate::autofix::Fix;
|
||||||
|
use crate::flake8_quotes::settings::Quote;
|
||||||
use crate::pyupgrade::types::Primitive;
|
use crate::pyupgrade::types::Primitive;
|
||||||
|
|
||||||
#[derive(
|
#[derive(
|
||||||
|
|
@ -102,6 +103,11 @@ pub enum CheckCode {
|
||||||
// flake8-print
|
// flake8-print
|
||||||
T201,
|
T201,
|
||||||
T203,
|
T203,
|
||||||
|
// flake8-quotes
|
||||||
|
Q000,
|
||||||
|
Q001,
|
||||||
|
Q002,
|
||||||
|
Q003,
|
||||||
// pyupgrade
|
// pyupgrade
|
||||||
U001,
|
U001,
|
||||||
U002,
|
U002,
|
||||||
|
|
@ -184,6 +190,7 @@ pub enum CheckCategory {
|
||||||
Flake8Bugbear,
|
Flake8Bugbear,
|
||||||
Flake8Builtins,
|
Flake8Builtins,
|
||||||
Flake8Print,
|
Flake8Print,
|
||||||
|
Flake8Quotes,
|
||||||
Meta,
|
Meta,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -197,6 +204,7 @@ impl CheckCategory {
|
||||||
CheckCategory::Flake8Bugbear => "flake8-bugbear",
|
CheckCategory::Flake8Bugbear => "flake8-bugbear",
|
||||||
CheckCategory::Flake8Comprehensions => "flake8-comprehensions",
|
CheckCategory::Flake8Comprehensions => "flake8-comprehensions",
|
||||||
CheckCategory::Flake8Print => "flake8-print",
|
CheckCategory::Flake8Print => "flake8-print",
|
||||||
|
CheckCategory::Flake8Quotes => "flake8-quotes",
|
||||||
CheckCategory::Pyupgrade => "pyupgrade",
|
CheckCategory::Pyupgrade => "pyupgrade",
|
||||||
CheckCategory::Pydocstyle => "pydocstyle",
|
CheckCategory::Pydocstyle => "pydocstyle",
|
||||||
CheckCategory::PEP8Naming => "pep8-naming",
|
CheckCategory::PEP8Naming => "pep8-naming",
|
||||||
|
|
@ -299,6 +307,11 @@ pub enum CheckKind {
|
||||||
// flake8-print
|
// flake8-print
|
||||||
PrintFound,
|
PrintFound,
|
||||||
PPrintFound,
|
PPrintFound,
|
||||||
|
// flake8-quotes
|
||||||
|
BadQuotesInlineString(Quote),
|
||||||
|
BadQuotesMultilineString(Quote),
|
||||||
|
BadQuotesDocstring(Quote),
|
||||||
|
AvoidQuoteEscape,
|
||||||
// pyupgrade
|
// pyupgrade
|
||||||
TypeOfPrimitive(Primitive),
|
TypeOfPrimitive(Primitive),
|
||||||
UnnecessaryAbspath,
|
UnnecessaryAbspath,
|
||||||
|
|
@ -374,7 +387,11 @@ impl CheckCode {
|
||||||
pub fn lint_source(&self) -> &'static LintSource {
|
pub fn lint_source(&self) -> &'static LintSource {
|
||||||
match self {
|
match self {
|
||||||
CheckCode::E501 | CheckCode::W292 | CheckCode::M001 => &LintSource::Lines,
|
CheckCode::E501 | CheckCode::W292 | CheckCode::M001 => &LintSource::Lines,
|
||||||
CheckCode::W605 => &LintSource::Tokens,
|
CheckCode::W605
|
||||||
|
| CheckCode::Q000
|
||||||
|
| CheckCode::Q001
|
||||||
|
| CheckCode::Q002
|
||||||
|
| CheckCode::Q003 => &LintSource::Tokens,
|
||||||
CheckCode::E902 => &LintSource::FileSystem,
|
CheckCode::E902 => &LintSource::FileSystem,
|
||||||
_ => &LintSource::AST,
|
_ => &LintSource::AST,
|
||||||
}
|
}
|
||||||
|
|
@ -476,6 +493,11 @@ impl CheckCode {
|
||||||
// flake8-print
|
// flake8-print
|
||||||
CheckCode::T201 => CheckKind::PrintFound,
|
CheckCode::T201 => CheckKind::PrintFound,
|
||||||
CheckCode::T203 => CheckKind::PPrintFound,
|
CheckCode::T203 => CheckKind::PPrintFound,
|
||||||
|
// flake8-quotes
|
||||||
|
CheckCode::Q000 => CheckKind::BadQuotesInlineString(Quote::Double),
|
||||||
|
CheckCode::Q001 => CheckKind::BadQuotesMultilineString(Quote::Double),
|
||||||
|
CheckCode::Q002 => CheckKind::BadQuotesDocstring(Quote::Double),
|
||||||
|
CheckCode::Q003 => CheckKind::AvoidQuoteEscape,
|
||||||
// pyupgrade
|
// pyupgrade
|
||||||
CheckCode::U001 => CheckKind::UselessMetaclassType,
|
CheckCode::U001 => CheckKind::UselessMetaclassType,
|
||||||
CheckCode::U002 => CheckKind::UnnecessaryAbspath,
|
CheckCode::U002 => CheckKind::UnnecessaryAbspath,
|
||||||
|
|
@ -639,6 +661,10 @@ impl CheckCode {
|
||||||
CheckCode::C417 => CheckCategory::Flake8Comprehensions,
|
CheckCode::C417 => CheckCategory::Flake8Comprehensions,
|
||||||
CheckCode::T201 => CheckCategory::Flake8Print,
|
CheckCode::T201 => CheckCategory::Flake8Print,
|
||||||
CheckCode::T203 => CheckCategory::Flake8Print,
|
CheckCode::T203 => CheckCategory::Flake8Print,
|
||||||
|
CheckCode::Q000 => CheckCategory::Flake8Quotes,
|
||||||
|
CheckCode::Q001 => CheckCategory::Flake8Quotes,
|
||||||
|
CheckCode::Q002 => CheckCategory::Flake8Quotes,
|
||||||
|
CheckCode::Q003 => CheckCategory::Flake8Quotes,
|
||||||
CheckCode::U001 => CheckCategory::Pyupgrade,
|
CheckCode::U001 => CheckCategory::Pyupgrade,
|
||||||
CheckCode::U002 => CheckCategory::Pyupgrade,
|
CheckCode::U002 => CheckCategory::Pyupgrade,
|
||||||
CheckCode::U003 => CheckCategory::Pyupgrade,
|
CheckCode::U003 => CheckCategory::Pyupgrade,
|
||||||
|
|
@ -788,6 +814,11 @@ impl CheckKind {
|
||||||
// flake8-print
|
// flake8-print
|
||||||
CheckKind::PrintFound => &CheckCode::T201,
|
CheckKind::PrintFound => &CheckCode::T201,
|
||||||
CheckKind::PPrintFound => &CheckCode::T203,
|
CheckKind::PPrintFound => &CheckCode::T203,
|
||||||
|
// flake8-quotes
|
||||||
|
CheckKind::BadQuotesInlineString(_) => &CheckCode::Q000,
|
||||||
|
CheckKind::BadQuotesMultilineString(_) => &CheckCode::Q001,
|
||||||
|
CheckKind::BadQuotesDocstring(_) => &CheckCode::Q002,
|
||||||
|
CheckKind::AvoidQuoteEscape => &CheckCode::Q003,
|
||||||
// pyupgrade
|
// pyupgrade
|
||||||
CheckKind::TypeOfPrimitive(_) => &CheckCode::U003,
|
CheckKind::TypeOfPrimitive(_) => &CheckCode::U003,
|
||||||
CheckKind::UnnecessaryAbspath => &CheckCode::U002,
|
CheckKind::UnnecessaryAbspath => &CheckCode::U002,
|
||||||
|
|
@ -1101,6 +1132,26 @@ impl CheckKind {
|
||||||
// flake8-print
|
// flake8-print
|
||||||
CheckKind::PrintFound => "`print` found".to_string(),
|
CheckKind::PrintFound => "`print` found".to_string(),
|
||||||
CheckKind::PPrintFound => "`pprint` found".to_string(),
|
CheckKind::PPrintFound => "`pprint` found".to_string(),
|
||||||
|
// flake8-quotes
|
||||||
|
CheckKind::BadQuotesInlineString(quote) => {
|
||||||
|
match quote {
|
||||||
|
Quote::Single => "Double quotes found but single quotes preferred".to_string(),
|
||||||
|
Quote::Double => "Single quotes found but double quotes preferred".to_string(),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
CheckKind::BadQuotesMultilineString(quote) => {
|
||||||
|
match quote {
|
||||||
|
Quote::Single => "Double quote multiline found but single quotes preferred".to_string(),
|
||||||
|
Quote::Double => "Single quote multiline found but double quotes preferred".to_string(),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
CheckKind::BadQuotesDocstring(quote) => {
|
||||||
|
match quote {
|
||||||
|
Quote::Single => "Double quote docstring found but single quotes preferred".to_string(),
|
||||||
|
Quote::Double => "Single quote docstring found but double quotes preferred".to_string(),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
CheckKind::AvoidQuoteEscape => "Change outer quotes to avoid escaping inner quotes".to_string(),
|
||||||
// pyupgrade
|
// pyupgrade
|
||||||
CheckKind::TypeOfPrimitive(primitive) => {
|
CheckKind::TypeOfPrimitive(primitive) => {
|
||||||
format!("Use `{}` instead of `type(...)`", primitive.builtin())
|
format!("Use `{}` instead of `type(...)`", primitive.builtin())
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,303 @@
|
||||||
|
use rustpython_ast::Location;
|
||||||
|
|
||||||
|
use crate::ast::operations::SourceCodeLocator;
|
||||||
|
use crate::ast::types::Range;
|
||||||
|
use crate::checks::{Check, CheckKind};
|
||||||
|
use crate::flake8_quotes::settings::{Quote, Settings};
|
||||||
|
|
||||||
|
fn good_single(quote: &Quote) -> char {
|
||||||
|
match quote {
|
||||||
|
Quote::Single => '\'',
|
||||||
|
Quote::Double => '"',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn bad_single(quote: &Quote) -> char {
|
||||||
|
match quote {
|
||||||
|
Quote::Double => '\'',
|
||||||
|
Quote::Single => '"',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn good_multiline(quote: &Quote) -> &str {
|
||||||
|
match quote {
|
||||||
|
Quote::Single => "'''",
|
||||||
|
Quote::Double => "\"\"\"",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn good_multiline_ending(quote: &Quote) -> &str {
|
||||||
|
match quote {
|
||||||
|
Quote::Single => "'\"\"\"",
|
||||||
|
Quote::Double => "\"'''",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn good_docstring(quote: &Quote) -> &str {
|
||||||
|
match quote {
|
||||||
|
Quote::Single => "'''",
|
||||||
|
Quote::Double => "\"\"\"",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn quotes(
|
||||||
|
locator: &SourceCodeLocator,
|
||||||
|
start: &Location,
|
||||||
|
end: &Location,
|
||||||
|
is_docstring: bool,
|
||||||
|
settings: &Settings,
|
||||||
|
) -> Option<Check> {
|
||||||
|
let text = locator.slice_source_code_range(&Range {
|
||||||
|
location: *start,
|
||||||
|
end_location: *end,
|
||||||
|
});
|
||||||
|
|
||||||
|
// 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..];
|
||||||
|
|
||||||
|
// Determine if the string is multiline-based.
|
||||||
|
let is_multiline = if raw_text.len() >= 3 {
|
||||||
|
let mut chars = raw_text.chars();
|
||||||
|
let first = chars.next().unwrap();
|
||||||
|
let second = chars.next().unwrap();
|
||||||
|
let third = chars.next().unwrap();
|
||||||
|
first == second && second == third
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
};
|
||||||
|
|
||||||
|
if is_docstring {
|
||||||
|
if raw_text.contains(good_docstring(&settings.docstring_quotes)) {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Some(Check::new(
|
||||||
|
CheckKind::BadQuotesDocstring(settings.docstring_quotes.clone()),
|
||||||
|
Range {
|
||||||
|
location: *start,
|
||||||
|
end_location: *end,
|
||||||
|
},
|
||||||
|
));
|
||||||
|
} else if is_multiline {
|
||||||
|
// If our string is or contains a known good string, ignore it.
|
||||||
|
if raw_text.contains(good_multiline(&settings.multiline_quotes)) {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If our string ends with a known good ending, then ignore it.
|
||||||
|
if raw_text.ends_with(good_multiline_ending(&settings.multiline_quotes)) {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Some(Check::new(
|
||||||
|
CheckKind::BadQuotesMultilineString(settings.multiline_quotes.clone()),
|
||||||
|
Range {
|
||||||
|
location: *start,
|
||||||
|
end_location: *end,
|
||||||
|
},
|
||||||
|
));
|
||||||
|
} else {
|
||||||
|
let string_contents = &raw_text[1..raw_text.len() - 1];
|
||||||
|
|
||||||
|
// If we're using the preferred quotation type, check for escapes.
|
||||||
|
if last_quote_char == good_single(&settings.inline_quotes) {
|
||||||
|
if !settings.avoid_escape || prefix.contains('r') {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
if string_contents.contains(good_single(&settings.inline_quotes))
|
||||||
|
&& !string_contents.contains(bad_single(&settings.inline_quotes))
|
||||||
|
{
|
||||||
|
return Some(Check::new(
|
||||||
|
CheckKind::AvoidQuoteEscape,
|
||||||
|
Range {
|
||||||
|
location: *start,
|
||||||
|
end_location: *end,
|
||||||
|
},
|
||||||
|
));
|
||||||
|
}
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we're not using the preferred type, only allow use to avoid escapes.
|
||||||
|
if !string_contents.contains(good_single(&settings.inline_quotes)) {
|
||||||
|
return Some(Check::new(
|
||||||
|
CheckKind::BadQuotesInlineString(settings.inline_quotes.clone()),
|
||||||
|
Range {
|
||||||
|
location: *start,
|
||||||
|
end_location: *end,
|
||||||
|
},
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use std::path::Path;
|
||||||
|
|
||||||
|
use anyhow::Result;
|
||||||
|
use rustpython_parser::lexer::LexResult;
|
||||||
|
use test_case::test_case;
|
||||||
|
|
||||||
|
use crate::autofix::fixer;
|
||||||
|
use crate::checks::{Check, CheckCode};
|
||||||
|
use crate::flake8_quotes::settings::Quote;
|
||||||
|
use crate::linter::tokenize;
|
||||||
|
use crate::settings;
|
||||||
|
use crate::{flake8_quotes, linter};
|
||||||
|
use crate::{fs, noqa};
|
||||||
|
|
||||||
|
fn check_path(
|
||||||
|
path: &Path,
|
||||||
|
settings: &settings::Settings,
|
||||||
|
autofix: &fixer::Mode,
|
||||||
|
) -> Result<Vec<Check>> {
|
||||||
|
let contents = fs::read_file(path)?;
|
||||||
|
let tokens: Vec<LexResult> = tokenize(&contents);
|
||||||
|
let noqa_line_for = noqa::extract_noqa_line_for(&tokens);
|
||||||
|
linter::check_path(path, &contents, tokens, &noqa_line_for, settings, autofix)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test_case(Path::new("doubles.py"))]
|
||||||
|
#[test_case(Path::new("doubles_escaped.py"))]
|
||||||
|
#[test_case(Path::new("doubles_multiline_string.py"))]
|
||||||
|
#[test_case(Path::new("doubles_noqa.py"))]
|
||||||
|
#[test_case(Path::new("doubles_wrapped.py"))]
|
||||||
|
fn doubles(path: &Path) -> Result<()> {
|
||||||
|
let snapshot = format!("doubles_{}", path.to_string_lossy());
|
||||||
|
let mut checks = check_path(
|
||||||
|
Path::new("./resources/test/fixtures/flake8_quotes")
|
||||||
|
.join(path)
|
||||||
|
.as_path(),
|
||||||
|
&settings::Settings {
|
||||||
|
flake8_quotes: flake8_quotes::settings::Settings {
|
||||||
|
inline_quotes: Quote::Single,
|
||||||
|
multiline_quotes: Quote::Single,
|
||||||
|
docstring_quotes: Quote::Single,
|
||||||
|
avoid_escape: true,
|
||||||
|
},
|
||||||
|
..settings::Settings::for_rules(vec![
|
||||||
|
CheckCode::Q000,
|
||||||
|
CheckCode::Q001,
|
||||||
|
CheckCode::Q002,
|
||||||
|
CheckCode::Q003,
|
||||||
|
])
|
||||||
|
},
|
||||||
|
&fixer::Mode::Generate,
|
||||||
|
)?;
|
||||||
|
checks.sort_by_key(|check| check.location);
|
||||||
|
insta::assert_yaml_snapshot!(snapshot, checks);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test_case(Path::new("singles.py"))]
|
||||||
|
#[test_case(Path::new("singles_escaped.py"))]
|
||||||
|
#[test_case(Path::new("singles_multiline_string.py"))]
|
||||||
|
#[test_case(Path::new("singles_noqa.py"))]
|
||||||
|
#[test_case(Path::new("singles_wrapped.py"))]
|
||||||
|
fn singles(path: &Path) -> Result<()> {
|
||||||
|
let snapshot = format!("singles_{}", path.to_string_lossy());
|
||||||
|
let mut checks = check_path(
|
||||||
|
Path::new("./resources/test/fixtures/flake8_quotes")
|
||||||
|
.join(path)
|
||||||
|
.as_path(),
|
||||||
|
&settings::Settings {
|
||||||
|
flake8_quotes: flake8_quotes::settings::Settings {
|
||||||
|
inline_quotes: Quote::Double,
|
||||||
|
multiline_quotes: Quote::Double,
|
||||||
|
docstring_quotes: Quote::Double,
|
||||||
|
avoid_escape: true,
|
||||||
|
},
|
||||||
|
..settings::Settings::for_rules(vec![
|
||||||
|
CheckCode::Q000,
|
||||||
|
CheckCode::Q001,
|
||||||
|
CheckCode::Q002,
|
||||||
|
CheckCode::Q003,
|
||||||
|
])
|
||||||
|
},
|
||||||
|
&fixer::Mode::Generate,
|
||||||
|
)?;
|
||||||
|
checks.sort_by_key(|check| check.location);
|
||||||
|
insta::assert_yaml_snapshot!(snapshot, checks);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test_case(Path::new("docstring_doubles.py"))]
|
||||||
|
#[test_case(Path::new("docstring_doubles_module_multiline.py"))]
|
||||||
|
#[test_case(Path::new("docstring_doubles_module_singleline.py"))]
|
||||||
|
#[test_case(Path::new("docstring_doubles_class.py"))]
|
||||||
|
#[test_case(Path::new("docstring_doubles_function.py"))]
|
||||||
|
#[test_case(Path::new("docstring_singles.py"))]
|
||||||
|
#[test_case(Path::new("docstring_singles_module_multiline.py"))]
|
||||||
|
#[test_case(Path::new("docstring_singles_module_singleline.py"))]
|
||||||
|
#[test_case(Path::new("docstring_singles_class.py"))]
|
||||||
|
#[test_case(Path::new("docstring_singles_function.py"))]
|
||||||
|
fn double_docstring(path: &Path) -> Result<()> {
|
||||||
|
let snapshot = format!("double_docstring_{}", path.to_string_lossy());
|
||||||
|
let mut checks = check_path(
|
||||||
|
Path::new("./resources/test/fixtures/flake8_quotes")
|
||||||
|
.join(path)
|
||||||
|
.as_path(),
|
||||||
|
&settings::Settings {
|
||||||
|
flake8_quotes: flake8_quotes::settings::Settings {
|
||||||
|
inline_quotes: Quote::Single,
|
||||||
|
multiline_quotes: Quote::Single,
|
||||||
|
docstring_quotes: Quote::Double,
|
||||||
|
avoid_escape: true,
|
||||||
|
},
|
||||||
|
..settings::Settings::for_rules(vec![
|
||||||
|
CheckCode::Q000,
|
||||||
|
CheckCode::Q001,
|
||||||
|
CheckCode::Q002,
|
||||||
|
CheckCode::Q003,
|
||||||
|
])
|
||||||
|
},
|
||||||
|
&fixer::Mode::Generate,
|
||||||
|
)?;
|
||||||
|
checks.sort_by_key(|check| check.location);
|
||||||
|
insta::assert_yaml_snapshot!(snapshot, checks);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test_case(Path::new("docstring_doubles.py"))]
|
||||||
|
#[test_case(Path::new("docstring_doubles_module_multiline.py"))]
|
||||||
|
#[test_case(Path::new("docstring_doubles_module_singleline.py"))]
|
||||||
|
#[test_case(Path::new("docstring_doubles_class.py"))]
|
||||||
|
#[test_case(Path::new("docstring_doubles_function.py"))]
|
||||||
|
#[test_case(Path::new("docstring_singles.py"))]
|
||||||
|
#[test_case(Path::new("docstring_singles_module_multiline.py"))]
|
||||||
|
#[test_case(Path::new("docstring_singles_module_singleline.py"))]
|
||||||
|
#[test_case(Path::new("docstring_singles_class.py"))]
|
||||||
|
#[test_case(Path::new("docstring_singles_function.py"))]
|
||||||
|
fn single_docstring(path: &Path) -> Result<()> {
|
||||||
|
let snapshot = format!("single_docstring_{}", path.to_string_lossy());
|
||||||
|
let mut checks = check_path(
|
||||||
|
Path::new("./resources/test/fixtures/flake8_quotes")
|
||||||
|
.join(path)
|
||||||
|
.as_path(),
|
||||||
|
&settings::Settings {
|
||||||
|
flake8_quotes: flake8_quotes::settings::Settings {
|
||||||
|
inline_quotes: Quote::Single,
|
||||||
|
multiline_quotes: Quote::Double,
|
||||||
|
docstring_quotes: Quote::Single,
|
||||||
|
avoid_escape: true,
|
||||||
|
},
|
||||||
|
..settings::Settings::for_rules(vec![
|
||||||
|
CheckCode::Q000,
|
||||||
|
CheckCode::Q001,
|
||||||
|
CheckCode::Q002,
|
||||||
|
CheckCode::Q003,
|
||||||
|
])
|
||||||
|
},
|
||||||
|
&fixer::Mode::Generate,
|
||||||
|
)?;
|
||||||
|
checks.sort_by_key(|check| check.location);
|
||||||
|
insta::assert_yaml_snapshot!(snapshot, checks);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,118 @@
|
||||||
|
//! Extract docstrings via tokenization.
|
||||||
|
//!
|
||||||
|
//! See: https://github.com/zheller/flake8-quotes/blob/ef0d9a90249a080e460b70ab62bf4b65e5aa5816/flake8_quotes/docstring_detection.py#L29
|
||||||
|
//!
|
||||||
|
//! TODO(charlie): Consolidate with the existing AST-based docstring extraction.
|
||||||
|
|
||||||
|
use rustpython_parser::lexer::Tok;
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
enum State {
|
||||||
|
// Start of the module: first string gets marked as a docstring.
|
||||||
|
ExpectModuleDocstring,
|
||||||
|
// After seeing a class definition, we're waiting for the block colon (and do bracket counting).
|
||||||
|
ExpectClassColon,
|
||||||
|
// After seeing the block colon in a class definition, we expect a docstring.
|
||||||
|
ExpectClassDocstring,
|
||||||
|
// Same as ExpectClassColon, but for function definitions.
|
||||||
|
ExpectFunctionColon,
|
||||||
|
// Same as ExpectClassDocstring, but for function definitions.
|
||||||
|
ExpectFunctionDocstring,
|
||||||
|
// Skip tokens until we observe a `class` or `def`.
|
||||||
|
Other,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct StateMachine {
|
||||||
|
state: State,
|
||||||
|
bracket_count: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl StateMachine {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
state: State::ExpectModuleDocstring,
|
||||||
|
bracket_count: 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn consume(&mut self, tok: &Tok) -> bool {
|
||||||
|
if matches!(tok, Tok::Newline | Tok::Indent | Tok::Dedent) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if matches!(tok, Tok::String { .. }) {
|
||||||
|
return if matches!(
|
||||||
|
self.state,
|
||||||
|
State::ExpectModuleDocstring
|
||||||
|
| State::ExpectClassDocstring
|
||||||
|
| State::ExpectFunctionDocstring
|
||||||
|
) {
|
||||||
|
self.state = State::Other;
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if matches!(tok, Tok::Class) {
|
||||||
|
self.state = State::ExpectClassColon;
|
||||||
|
self.bracket_count = 0;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if matches!(tok, Tok::Def) {
|
||||||
|
self.state = State::ExpectFunctionColon;
|
||||||
|
self.bracket_count = 0;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if matches!(tok, Tok::Colon) {
|
||||||
|
if self.bracket_count == 0 {
|
||||||
|
if matches!(self.state, State::ExpectClassColon) {
|
||||||
|
self.state = State::ExpectClassDocstring;
|
||||||
|
} else if matches!(self.state, State::ExpectFunctionColon) {
|
||||||
|
self.state = State::ExpectFunctionDocstring;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if matches!(tok, Tok::Lpar | Tok::Lbrace | Tok::Lsqb) {
|
||||||
|
self.bracket_count += 1;
|
||||||
|
if matches!(
|
||||||
|
self.state,
|
||||||
|
State::ExpectModuleDocstring
|
||||||
|
| State::ExpectClassDocstring
|
||||||
|
| State::ExpectFunctionDocstring
|
||||||
|
) {
|
||||||
|
self.state = State::Other;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if matches!(tok, Tok::Rpar | Tok::Rbrace | Tok::Rsqb) {
|
||||||
|
self.bracket_count -= 1;
|
||||||
|
if matches!(
|
||||||
|
self.state,
|
||||||
|
State::ExpectModuleDocstring
|
||||||
|
| State::ExpectClassDocstring
|
||||||
|
| State::ExpectFunctionDocstring
|
||||||
|
) {
|
||||||
|
self.state = State::Other;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if matches!(
|
||||||
|
self.state,
|
||||||
|
State::ExpectModuleDocstring
|
||||||
|
| State::ExpectClassDocstring
|
||||||
|
| State::ExpectFunctionDocstring
|
||||||
|
) {
|
||||||
|
self.state = State::Other;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
pub mod checks;
|
||||||
|
pub mod docstring_detection;
|
||||||
|
pub mod settings;
|
||||||
|
|
@ -0,0 +1,49 @@
|
||||||
|
//! Settings for the `flake_quotes` plugin.
|
||||||
|
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)]
|
||||||
|
#[serde(deny_unknown_fields, rename_all = "kebab-case")]
|
||||||
|
pub enum Quote {
|
||||||
|
Single,
|
||||||
|
Double,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Eq, Deserialize)]
|
||||||
|
#[serde(deny_unknown_fields, rename_all = "kebab-case")]
|
||||||
|
pub struct Config {
|
||||||
|
pub inline_quotes: Option<Quote>,
|
||||||
|
pub multiline_quotes: Option<Quote>,
|
||||||
|
pub docstring_quotes: Option<Quote>,
|
||||||
|
pub avoid_escape: Option<bool>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct Settings {
|
||||||
|
pub inline_quotes: Quote,
|
||||||
|
pub multiline_quotes: Quote,
|
||||||
|
pub docstring_quotes: Quote,
|
||||||
|
pub avoid_escape: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Settings {
|
||||||
|
pub fn from_config(config: Config) -> Self {
|
||||||
|
Self {
|
||||||
|
inline_quotes: config.inline_quotes.unwrap_or(Quote::Single),
|
||||||
|
multiline_quotes: config.multiline_quotes.unwrap_or(Quote::Double),
|
||||||
|
docstring_quotes: config.docstring_quotes.unwrap_or(Quote::Double),
|
||||||
|
avoid_escape: config.avoid_escape.unwrap_or(true),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for Settings {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
inline_quotes: Quote::Single,
|
||||||
|
multiline_quotes: Quote::Double,
|
||||||
|
docstring_quotes: Quote::Double,
|
||||||
|
avoid_escape: true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,50 @@
|
||||||
|
---
|
||||||
|
source: src/flake8_quotes/checks.rs
|
||||||
|
expression: checks
|
||||||
|
---
|
||||||
|
- kind:
|
||||||
|
BadQuotesMultilineString: single
|
||||||
|
location:
|
||||||
|
row: 5
|
||||||
|
column: 1
|
||||||
|
end_location:
|
||||||
|
row: 7
|
||||||
|
column: 4
|
||||||
|
fix: ~
|
||||||
|
- kind:
|
||||||
|
BadQuotesMultilineString: single
|
||||||
|
location:
|
||||||
|
row: 16
|
||||||
|
column: 5
|
||||||
|
end_location:
|
||||||
|
row: 18
|
||||||
|
column: 8
|
||||||
|
fix: ~
|
||||||
|
- kind:
|
||||||
|
BadQuotesMultilineString: single
|
||||||
|
location:
|
||||||
|
row: 21
|
||||||
|
column: 21
|
||||||
|
end_location:
|
||||||
|
row: 22
|
||||||
|
column: 38
|
||||||
|
fix: ~
|
||||||
|
- kind:
|
||||||
|
BadQuotesMultilineString: single
|
||||||
|
location:
|
||||||
|
row: 30
|
||||||
|
column: 9
|
||||||
|
end_location:
|
||||||
|
row: 32
|
||||||
|
column: 12
|
||||||
|
fix: ~
|
||||||
|
- kind:
|
||||||
|
BadQuotesMultilineString: single
|
||||||
|
location:
|
||||||
|
row: 35
|
||||||
|
column: 13
|
||||||
|
end_location:
|
||||||
|
row: 37
|
||||||
|
column: 16
|
||||||
|
fix: ~
|
||||||
|
|
||||||
|
|
@ -0,0 +1,23 @@
|
||||||
|
---
|
||||||
|
source: src/flake8_quotes/checks.rs
|
||||||
|
expression: checks
|
||||||
|
---
|
||||||
|
- kind:
|
||||||
|
BadQuotesMultilineString: single
|
||||||
|
location:
|
||||||
|
row: 3
|
||||||
|
column: 5
|
||||||
|
end_location:
|
||||||
|
row: 3
|
||||||
|
column: 28
|
||||||
|
fix: ~
|
||||||
|
- kind:
|
||||||
|
BadQuotesMultilineString: single
|
||||||
|
location:
|
||||||
|
row: 5
|
||||||
|
column: 23
|
||||||
|
end_location:
|
||||||
|
row: 5
|
||||||
|
column: 44
|
||||||
|
fix: ~
|
||||||
|
|
||||||
|
|
@ -0,0 +1,50 @@
|
||||||
|
---
|
||||||
|
source: src/flake8_quotes/checks.rs
|
||||||
|
expression: checks
|
||||||
|
---
|
||||||
|
- kind:
|
||||||
|
BadQuotesMultilineString: single
|
||||||
|
location:
|
||||||
|
row: 3
|
||||||
|
column: 5
|
||||||
|
end_location:
|
||||||
|
row: 3
|
||||||
|
column: 27
|
||||||
|
fix: ~
|
||||||
|
- kind:
|
||||||
|
BadQuotesMultilineString: single
|
||||||
|
location:
|
||||||
|
row: 11
|
||||||
|
column: 5
|
||||||
|
end_location:
|
||||||
|
row: 11
|
||||||
|
column: 27
|
||||||
|
fix: ~
|
||||||
|
- kind:
|
||||||
|
BadQuotesMultilineString: single
|
||||||
|
location:
|
||||||
|
row: 15
|
||||||
|
column: 39
|
||||||
|
end_location:
|
||||||
|
row: 17
|
||||||
|
column: 4
|
||||||
|
fix: ~
|
||||||
|
- kind:
|
||||||
|
BadQuotesMultilineString: single
|
||||||
|
location:
|
||||||
|
row: 17
|
||||||
|
column: 5
|
||||||
|
end_location:
|
||||||
|
row: 17
|
||||||
|
column: 20
|
||||||
|
fix: ~
|
||||||
|
- kind:
|
||||||
|
BadQuotesMultilineString: single
|
||||||
|
location:
|
||||||
|
row: 21
|
||||||
|
column: 5
|
||||||
|
end_location:
|
||||||
|
row: 21
|
||||||
|
column: 28
|
||||||
|
fix: ~
|
||||||
|
|
||||||
|
|
@ -0,0 +1,23 @@
|
||||||
|
---
|
||||||
|
source: src/flake8_quotes/checks.rs
|
||||||
|
expression: checks
|
||||||
|
---
|
||||||
|
- kind:
|
||||||
|
BadQuotesMultilineString: single
|
||||||
|
location:
|
||||||
|
row: 4
|
||||||
|
column: 1
|
||||||
|
end_location:
|
||||||
|
row: 6
|
||||||
|
column: 4
|
||||||
|
fix: ~
|
||||||
|
- kind:
|
||||||
|
BadQuotesMultilineString: single
|
||||||
|
location:
|
||||||
|
row: 9
|
||||||
|
column: 1
|
||||||
|
end_location:
|
||||||
|
row: 11
|
||||||
|
column: 4
|
||||||
|
fix: ~
|
||||||
|
|
||||||
|
|
@ -0,0 +1,23 @@
|
||||||
|
---
|
||||||
|
source: src/flake8_quotes/checks.rs
|
||||||
|
expression: checks
|
||||||
|
---
|
||||||
|
- kind:
|
||||||
|
BadQuotesMultilineString: single
|
||||||
|
location:
|
||||||
|
row: 2
|
||||||
|
column: 1
|
||||||
|
end_location:
|
||||||
|
row: 2
|
||||||
|
column: 32
|
||||||
|
fix: ~
|
||||||
|
- kind:
|
||||||
|
BadQuotesMultilineString: single
|
||||||
|
location:
|
||||||
|
row: 6
|
||||||
|
column: 1
|
||||||
|
end_location:
|
||||||
|
row: 6
|
||||||
|
column: 32
|
||||||
|
fix: ~
|
||||||
|
|
||||||
|
|
@ -0,0 +1,32 @@
|
||||||
|
---
|
||||||
|
source: src/flake8_quotes/checks.rs
|
||||||
|
expression: checks
|
||||||
|
---
|
||||||
|
- kind:
|
||||||
|
BadQuotesDocstring: double
|
||||||
|
location:
|
||||||
|
row: 1
|
||||||
|
column: 1
|
||||||
|
end_location:
|
||||||
|
row: 3
|
||||||
|
column: 4
|
||||||
|
fix: ~
|
||||||
|
- kind:
|
||||||
|
BadQuotesDocstring: double
|
||||||
|
location:
|
||||||
|
row: 14
|
||||||
|
column: 5
|
||||||
|
end_location:
|
||||||
|
row: 16
|
||||||
|
column: 8
|
||||||
|
fix: ~
|
||||||
|
- kind:
|
||||||
|
BadQuotesDocstring: double
|
||||||
|
location:
|
||||||
|
row: 26
|
||||||
|
column: 9
|
||||||
|
end_location:
|
||||||
|
row: 28
|
||||||
|
column: 12
|
||||||
|
fix: ~
|
||||||
|
|
||||||
|
|
@ -0,0 +1,32 @@
|
||||||
|
---
|
||||||
|
source: src/flake8_quotes/checks.rs
|
||||||
|
expression: checks
|
||||||
|
---
|
||||||
|
- kind:
|
||||||
|
BadQuotesDocstring: double
|
||||||
|
location:
|
||||||
|
row: 2
|
||||||
|
column: 5
|
||||||
|
end_location:
|
||||||
|
row: 2
|
||||||
|
column: 54
|
||||||
|
fix: ~
|
||||||
|
- kind:
|
||||||
|
BadQuotesDocstring: double
|
||||||
|
location:
|
||||||
|
row: 6
|
||||||
|
column: 9
|
||||||
|
end_location:
|
||||||
|
row: 6
|
||||||
|
column: 58
|
||||||
|
fix: ~
|
||||||
|
- kind:
|
||||||
|
BadQuotesDocstring: double
|
||||||
|
location:
|
||||||
|
row: 9
|
||||||
|
column: 29
|
||||||
|
end_location:
|
||||||
|
row: 9
|
||||||
|
column: 53
|
||||||
|
fix: ~
|
||||||
|
|
||||||
|
|
@ -0,0 +1,23 @@
|
||||||
|
---
|
||||||
|
source: src/flake8_quotes/checks.rs
|
||||||
|
expression: checks
|
||||||
|
---
|
||||||
|
- kind:
|
||||||
|
BadQuotesDocstring: double
|
||||||
|
location:
|
||||||
|
row: 2
|
||||||
|
column: 5
|
||||||
|
end_location:
|
||||||
|
row: 2
|
||||||
|
column: 57
|
||||||
|
fix: ~
|
||||||
|
- kind:
|
||||||
|
BadQuotesDocstring: double
|
||||||
|
location:
|
||||||
|
row: 8
|
||||||
|
column: 5
|
||||||
|
end_location:
|
||||||
|
row: 10
|
||||||
|
column: 8
|
||||||
|
fix: ~
|
||||||
|
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
---
|
||||||
|
source: src/flake8_quotes/checks.rs
|
||||||
|
expression: checks
|
||||||
|
---
|
||||||
|
- kind:
|
||||||
|
BadQuotesDocstring: double
|
||||||
|
location:
|
||||||
|
row: 1
|
||||||
|
column: 1
|
||||||
|
end_location:
|
||||||
|
row: 3
|
||||||
|
column: 4
|
||||||
|
fix: ~
|
||||||
|
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
---
|
||||||
|
source: src/flake8_quotes/checks.rs
|
||||||
|
expression: checks
|
||||||
|
---
|
||||||
|
- kind:
|
||||||
|
BadQuotesDocstring: double
|
||||||
|
location:
|
||||||
|
row: 1
|
||||||
|
column: 1
|
||||||
|
end_location:
|
||||||
|
row: 1
|
||||||
|
column: 50
|
||||||
|
fix: ~
|
||||||
|
|
||||||
|
|
@ -0,0 +1,23 @@
|
||||||
|
---
|
||||||
|
source: src/flake8_quotes/checks.rs
|
||||||
|
expression: checks
|
||||||
|
---
|
||||||
|
- kind:
|
||||||
|
BadQuotesInlineString: single
|
||||||
|
location:
|
||||||
|
row: 1
|
||||||
|
column: 25
|
||||||
|
end_location:
|
||||||
|
row: 1
|
||||||
|
column: 46
|
||||||
|
fix: ~
|
||||||
|
- kind:
|
||||||
|
BadQuotesInlineString: single
|
||||||
|
location:
|
||||||
|
row: 2
|
||||||
|
column: 25
|
||||||
|
end_location:
|
||||||
|
row: 2
|
||||||
|
column: 47
|
||||||
|
fix: ~
|
||||||
|
|
||||||
|
|
@ -0,0 +1,13 @@
|
||||||
|
---
|
||||||
|
source: src/flake8_quotes/checks.rs
|
||||||
|
expression: checks
|
||||||
|
---
|
||||||
|
- kind: AvoidQuoteEscape
|
||||||
|
location:
|
||||||
|
row: 1
|
||||||
|
column: 26
|
||||||
|
end_location:
|
||||||
|
row: 1
|
||||||
|
column: 48
|
||||||
|
fix: ~
|
||||||
|
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
---
|
||||||
|
source: src/flake8_quotes/checks.rs
|
||||||
|
expression: checks
|
||||||
|
---
|
||||||
|
- kind:
|
||||||
|
BadQuotesMultilineString: single
|
||||||
|
location:
|
||||||
|
row: 1
|
||||||
|
column: 5
|
||||||
|
end_location:
|
||||||
|
row: 3
|
||||||
|
column: 13
|
||||||
|
fix: ~
|
||||||
|
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
---
|
||||||
|
source: src/flake8_quotes/checks.rs
|
||||||
|
expression: checks
|
||||||
|
---
|
||||||
|
[]
|
||||||
|
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
---
|
||||||
|
source: src/flake8_quotes/checks.rs
|
||||||
|
expression: checks
|
||||||
|
---
|
||||||
|
[]
|
||||||
|
|
||||||
|
|
@ -0,0 +1,32 @@
|
||||||
|
---
|
||||||
|
source: src/flake8_quotes/checks.rs
|
||||||
|
expression: checks
|
||||||
|
---
|
||||||
|
- kind:
|
||||||
|
BadQuotesDocstring: single
|
||||||
|
location:
|
||||||
|
row: 1
|
||||||
|
column: 1
|
||||||
|
end_location:
|
||||||
|
row: 3
|
||||||
|
column: 4
|
||||||
|
fix: ~
|
||||||
|
- kind:
|
||||||
|
BadQuotesDocstring: single
|
||||||
|
location:
|
||||||
|
row: 12
|
||||||
|
column: 5
|
||||||
|
end_location:
|
||||||
|
row: 14
|
||||||
|
column: 8
|
||||||
|
fix: ~
|
||||||
|
- kind:
|
||||||
|
BadQuotesDocstring: single
|
||||||
|
location:
|
||||||
|
row: 24
|
||||||
|
column: 9
|
||||||
|
end_location:
|
||||||
|
row: 26
|
||||||
|
column: 12
|
||||||
|
fix: ~
|
||||||
|
|
||||||
|
|
@ -0,0 +1,32 @@
|
||||||
|
---
|
||||||
|
source: src/flake8_quotes/checks.rs
|
||||||
|
expression: checks
|
||||||
|
---
|
||||||
|
- kind:
|
||||||
|
BadQuotesDocstring: single
|
||||||
|
location:
|
||||||
|
row: 2
|
||||||
|
column: 5
|
||||||
|
end_location:
|
||||||
|
row: 2
|
||||||
|
column: 54
|
||||||
|
fix: ~
|
||||||
|
- kind:
|
||||||
|
BadQuotesDocstring: single
|
||||||
|
location:
|
||||||
|
row: 6
|
||||||
|
column: 9
|
||||||
|
end_location:
|
||||||
|
row: 6
|
||||||
|
column: 58
|
||||||
|
fix: ~
|
||||||
|
- kind:
|
||||||
|
BadQuotesDocstring: single
|
||||||
|
location:
|
||||||
|
row: 9
|
||||||
|
column: 29
|
||||||
|
end_location:
|
||||||
|
row: 9
|
||||||
|
column: 53
|
||||||
|
fix: ~
|
||||||
|
|
||||||
|
|
@ -0,0 +1,23 @@
|
||||||
|
---
|
||||||
|
source: src/flake8_quotes/checks.rs
|
||||||
|
expression: checks
|
||||||
|
---
|
||||||
|
- kind:
|
||||||
|
BadQuotesDocstring: single
|
||||||
|
location:
|
||||||
|
row: 2
|
||||||
|
column: 5
|
||||||
|
end_location:
|
||||||
|
row: 2
|
||||||
|
column: 57
|
||||||
|
fix: ~
|
||||||
|
- kind:
|
||||||
|
BadQuotesDocstring: single
|
||||||
|
location:
|
||||||
|
row: 8
|
||||||
|
column: 5
|
||||||
|
end_location:
|
||||||
|
row: 10
|
||||||
|
column: 8
|
||||||
|
fix: ~
|
||||||
|
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
---
|
||||||
|
source: src/flake8_quotes/checks.rs
|
||||||
|
expression: checks
|
||||||
|
---
|
||||||
|
- kind:
|
||||||
|
BadQuotesDocstring: single
|
||||||
|
location:
|
||||||
|
row: 1
|
||||||
|
column: 1
|
||||||
|
end_location:
|
||||||
|
row: 3
|
||||||
|
column: 4
|
||||||
|
fix: ~
|
||||||
|
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
---
|
||||||
|
source: src/flake8_quotes/checks.rs
|
||||||
|
expression: checks
|
||||||
|
---
|
||||||
|
- kind:
|
||||||
|
BadQuotesDocstring: single
|
||||||
|
location:
|
||||||
|
row: 1
|
||||||
|
column: 1
|
||||||
|
end_location:
|
||||||
|
row: 1
|
||||||
|
column: 50
|
||||||
|
fix: ~
|
||||||
|
|
||||||
|
|
@ -0,0 +1,59 @@
|
||||||
|
---
|
||||||
|
source: src/flake8_quotes/checks.rs
|
||||||
|
expression: checks
|
||||||
|
---
|
||||||
|
- kind:
|
||||||
|
BadQuotesMultilineString: double
|
||||||
|
location:
|
||||||
|
row: 5
|
||||||
|
column: 1
|
||||||
|
end_location:
|
||||||
|
row: 7
|
||||||
|
column: 4
|
||||||
|
fix: ~
|
||||||
|
- kind:
|
||||||
|
BadQuotesMultilineString: double
|
||||||
|
location:
|
||||||
|
row: 11
|
||||||
|
column: 21
|
||||||
|
end_location:
|
||||||
|
row: 13
|
||||||
|
column: 4
|
||||||
|
fix: ~
|
||||||
|
- kind:
|
||||||
|
BadQuotesMultilineString: double
|
||||||
|
location:
|
||||||
|
row: 18
|
||||||
|
column: 5
|
||||||
|
end_location:
|
||||||
|
row: 20
|
||||||
|
column: 8
|
||||||
|
fix: ~
|
||||||
|
- kind:
|
||||||
|
BadQuotesMultilineString: double
|
||||||
|
location:
|
||||||
|
row: 23
|
||||||
|
column: 21
|
||||||
|
end_location:
|
||||||
|
row: 24
|
||||||
|
column: 38
|
||||||
|
fix: ~
|
||||||
|
- kind:
|
||||||
|
BadQuotesMultilineString: double
|
||||||
|
location:
|
||||||
|
row: 32
|
||||||
|
column: 9
|
||||||
|
end_location:
|
||||||
|
row: 34
|
||||||
|
column: 12
|
||||||
|
fix: ~
|
||||||
|
- kind:
|
||||||
|
BadQuotesMultilineString: double
|
||||||
|
location:
|
||||||
|
row: 37
|
||||||
|
column: 13
|
||||||
|
end_location:
|
||||||
|
row: 39
|
||||||
|
column: 16
|
||||||
|
fix: ~
|
||||||
|
|
||||||
|
|
@ -0,0 +1,23 @@
|
||||||
|
---
|
||||||
|
source: src/flake8_quotes/checks.rs
|
||||||
|
expression: checks
|
||||||
|
---
|
||||||
|
- kind:
|
||||||
|
BadQuotesMultilineString: double
|
||||||
|
location:
|
||||||
|
row: 3
|
||||||
|
column: 5
|
||||||
|
end_location:
|
||||||
|
row: 3
|
||||||
|
column: 28
|
||||||
|
fix: ~
|
||||||
|
- kind:
|
||||||
|
BadQuotesMultilineString: double
|
||||||
|
location:
|
||||||
|
row: 5
|
||||||
|
column: 23
|
||||||
|
end_location:
|
||||||
|
row: 5
|
||||||
|
column: 44
|
||||||
|
fix: ~
|
||||||
|
|
||||||
|
|
@ -0,0 +1,50 @@
|
||||||
|
---
|
||||||
|
source: src/flake8_quotes/checks.rs
|
||||||
|
expression: checks
|
||||||
|
---
|
||||||
|
- kind:
|
||||||
|
BadQuotesMultilineString: double
|
||||||
|
location:
|
||||||
|
row: 3
|
||||||
|
column: 5
|
||||||
|
end_location:
|
||||||
|
row: 3
|
||||||
|
column: 27
|
||||||
|
fix: ~
|
||||||
|
- kind:
|
||||||
|
BadQuotesMultilineString: double
|
||||||
|
location:
|
||||||
|
row: 11
|
||||||
|
column: 5
|
||||||
|
end_location:
|
||||||
|
row: 11
|
||||||
|
column: 27
|
||||||
|
fix: ~
|
||||||
|
- kind:
|
||||||
|
BadQuotesMultilineString: double
|
||||||
|
location:
|
||||||
|
row: 15
|
||||||
|
column: 39
|
||||||
|
end_location:
|
||||||
|
row: 17
|
||||||
|
column: 4
|
||||||
|
fix: ~
|
||||||
|
- kind:
|
||||||
|
BadQuotesMultilineString: double
|
||||||
|
location:
|
||||||
|
row: 17
|
||||||
|
column: 5
|
||||||
|
end_location:
|
||||||
|
row: 17
|
||||||
|
column: 20
|
||||||
|
fix: ~
|
||||||
|
- kind:
|
||||||
|
BadQuotesMultilineString: double
|
||||||
|
location:
|
||||||
|
row: 21
|
||||||
|
column: 5
|
||||||
|
end_location:
|
||||||
|
row: 21
|
||||||
|
column: 28
|
||||||
|
fix: ~
|
||||||
|
|
||||||
|
|
@ -0,0 +1,23 @@
|
||||||
|
---
|
||||||
|
source: src/flake8_quotes/checks.rs
|
||||||
|
expression: checks
|
||||||
|
---
|
||||||
|
- kind:
|
||||||
|
BadQuotesMultilineString: double
|
||||||
|
location:
|
||||||
|
row: 4
|
||||||
|
column: 1
|
||||||
|
end_location:
|
||||||
|
row: 6
|
||||||
|
column: 4
|
||||||
|
fix: ~
|
||||||
|
- kind:
|
||||||
|
BadQuotesMultilineString: double
|
||||||
|
location:
|
||||||
|
row: 9
|
||||||
|
column: 1
|
||||||
|
end_location:
|
||||||
|
row: 11
|
||||||
|
column: 4
|
||||||
|
fix: ~
|
||||||
|
|
||||||
|
|
@ -0,0 +1,23 @@
|
||||||
|
---
|
||||||
|
source: src/flake8_quotes/checks.rs
|
||||||
|
expression: checks
|
||||||
|
---
|
||||||
|
- kind:
|
||||||
|
BadQuotesMultilineString: double
|
||||||
|
location:
|
||||||
|
row: 2
|
||||||
|
column: 1
|
||||||
|
end_location:
|
||||||
|
row: 2
|
||||||
|
column: 32
|
||||||
|
fix: ~
|
||||||
|
- kind:
|
||||||
|
BadQuotesMultilineString: double
|
||||||
|
location:
|
||||||
|
row: 6
|
||||||
|
column: 1
|
||||||
|
end_location:
|
||||||
|
row: 6
|
||||||
|
column: 32
|
||||||
|
fix: ~
|
||||||
|
|
||||||
|
|
@ -0,0 +1,23 @@
|
||||||
|
---
|
||||||
|
source: src/flake8_quotes/checks.rs
|
||||||
|
expression: checks
|
||||||
|
---
|
||||||
|
- kind:
|
||||||
|
BadQuotesInlineString: double
|
||||||
|
location:
|
||||||
|
row: 1
|
||||||
|
column: 25
|
||||||
|
end_location:
|
||||||
|
row: 1
|
||||||
|
column: 46
|
||||||
|
fix: ~
|
||||||
|
- kind:
|
||||||
|
BadQuotesInlineString: double
|
||||||
|
location:
|
||||||
|
row: 2
|
||||||
|
column: 25
|
||||||
|
end_location:
|
||||||
|
row: 2
|
||||||
|
column: 47
|
||||||
|
fix: ~
|
||||||
|
|
||||||
|
|
@ -0,0 +1,13 @@
|
||||||
|
---
|
||||||
|
source: src/flake8_quotes/checks.rs
|
||||||
|
expression: checks
|
||||||
|
---
|
||||||
|
- kind: AvoidQuoteEscape
|
||||||
|
location:
|
||||||
|
row: 1
|
||||||
|
column: 26
|
||||||
|
end_location:
|
||||||
|
row: 1
|
||||||
|
column: 48
|
||||||
|
fix: ~
|
||||||
|
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
---
|
||||||
|
source: src/flake8_quotes/checks.rs
|
||||||
|
expression: checks
|
||||||
|
---
|
||||||
|
- kind:
|
||||||
|
BadQuotesMultilineString: double
|
||||||
|
location:
|
||||||
|
row: 1
|
||||||
|
column: 5
|
||||||
|
end_location:
|
||||||
|
row: 3
|
||||||
|
column: 13
|
||||||
|
fix: ~
|
||||||
|
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
---
|
||||||
|
source: src/flake8_quotes/checks.rs
|
||||||
|
expression: checks
|
||||||
|
---
|
||||||
|
[]
|
||||||
|
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
---
|
||||||
|
source: src/flake8_quotes/checks.rs
|
||||||
|
expression: checks
|
||||||
|
---
|
||||||
|
[]
|
||||||
|
|
||||||
|
|
@ -26,6 +26,7 @@ mod flake8_bugbear;
|
||||||
mod flake8_builtins;
|
mod flake8_builtins;
|
||||||
mod flake8_comprehensions;
|
mod flake8_comprehensions;
|
||||||
mod flake8_print;
|
mod flake8_print;
|
||||||
|
mod flake8_quotes;
|
||||||
pub mod fs;
|
pub mod fs;
|
||||||
pub mod linter;
|
pub mod linter;
|
||||||
pub mod logging;
|
pub mod logging;
|
||||||
|
|
|
||||||
|
|
@ -8,8 +8,8 @@ use serde::de;
|
||||||
use serde::{Deserialize, Deserializer};
|
use serde::{Deserialize, Deserializer};
|
||||||
|
|
||||||
use crate::checks::CheckCode;
|
use crate::checks::CheckCode;
|
||||||
use crate::fs;
|
|
||||||
use crate::settings::PythonVersion;
|
use crate::settings::PythonVersion;
|
||||||
|
use crate::{flake8_quotes, fs};
|
||||||
|
|
||||||
pub fn load_config(pyproject: &Option<PathBuf>, quiet: bool) -> Result<Config> {
|
pub fn load_config(pyproject: &Option<PathBuf>, quiet: bool) -> Result<Config> {
|
||||||
match pyproject {
|
match pyproject {
|
||||||
|
|
@ -45,6 +45,7 @@ pub struct Config {
|
||||||
pub per_file_ignores: Vec<StrCheckCodePair>,
|
pub per_file_ignores: Vec<StrCheckCodePair>,
|
||||||
pub dummy_variable_rgx: Option<String>,
|
pub dummy_variable_rgx: Option<String>,
|
||||||
pub target_version: Option<PythonVersion>,
|
pub target_version: Option<PythonVersion>,
|
||||||
|
pub flake8_quotes: Option<flake8_quotes::settings::Config>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||||
|
|
@ -195,6 +196,7 @@ mod tests {
|
||||||
per_file_ignores: vec![],
|
per_file_ignores: vec![],
|
||||||
dummy_variable_rgx: None,
|
dummy_variable_rgx: None,
|
||||||
target_version: None,
|
target_version: None,
|
||||||
|
flake8_quotes: None
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
@ -220,6 +222,7 @@ line-length = 79
|
||||||
per_file_ignores: vec![],
|
per_file_ignores: vec![],
|
||||||
dummy_variable_rgx: None,
|
dummy_variable_rgx: None,
|
||||||
target_version: None,
|
target_version: None,
|
||||||
|
flake8_quotes: None
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
@ -245,6 +248,7 @@ exclude = ["foo.py"]
|
||||||
per_file_ignores: vec![],
|
per_file_ignores: vec![],
|
||||||
dummy_variable_rgx: None,
|
dummy_variable_rgx: None,
|
||||||
target_version: None,
|
target_version: None,
|
||||||
|
flake8_quotes: None
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
@ -270,6 +274,7 @@ select = ["E501"]
|
||||||
per_file_ignores: vec![],
|
per_file_ignores: vec![],
|
||||||
dummy_variable_rgx: None,
|
dummy_variable_rgx: None,
|
||||||
target_version: None,
|
target_version: None,
|
||||||
|
flake8_quotes: None
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
@ -296,6 +301,7 @@ ignore = ["E501"]
|
||||||
per_file_ignores: vec![],
|
per_file_ignores: vec![],
|
||||||
dummy_variable_rgx: None,
|
dummy_variable_rgx: None,
|
||||||
target_version: None,
|
target_version: None,
|
||||||
|
flake8_quotes: None
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
@ -368,6 +374,7 @@ other-attribute = 1
|
||||||
}],
|
}],
|
||||||
dummy_variable_rgx: None,
|
dummy_variable_rgx: None,
|
||||||
target_version: None,
|
target_version: None,
|
||||||
|
flake8_quotes: None
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -11,8 +11,8 @@ use serde::{Deserialize, Serialize};
|
||||||
use strum::IntoEnumIterator;
|
use strum::IntoEnumIterator;
|
||||||
|
|
||||||
use crate::checks::{CheckCategory, CheckCode};
|
use crate::checks::{CheckCategory, CheckCode};
|
||||||
use crate::fs;
|
|
||||||
use crate::pyproject::{load_config, StrCheckCodePair};
|
use crate::pyproject::{load_config, StrCheckCodePair};
|
||||||
|
use crate::{flake8_quotes, fs};
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialOrd, PartialEq, Eq, Serialize, Deserialize)]
|
#[derive(Clone, Debug, PartialOrd, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
pub enum PythonVersion {
|
pub enum PythonVersion {
|
||||||
|
|
@ -97,6 +97,8 @@ pub struct RawSettings {
|
||||||
pub per_file_ignores: Vec<PerFileIgnore>,
|
pub per_file_ignores: Vec<PerFileIgnore>,
|
||||||
pub select: Vec<CheckCode>,
|
pub select: Vec<CheckCode>,
|
||||||
pub target_version: PythonVersion,
|
pub target_version: PythonVersion,
|
||||||
|
// Plugins
|
||||||
|
pub flake8_quotes: flake8_quotes::settings::Settings,
|
||||||
}
|
}
|
||||||
|
|
||||||
static DEFAULT_EXCLUDE: Lazy<Vec<FilePattern>> = Lazy::new(|| {
|
static DEFAULT_EXCLUDE: Lazy<Vec<FilePattern>> = Lazy::new(|| {
|
||||||
|
|
@ -133,6 +135,7 @@ impl RawSettings {
|
||||||
quiet: bool,
|
quiet: bool,
|
||||||
) -> Result<Self> {
|
) -> Result<Self> {
|
||||||
let config = load_config(pyproject, quiet)?;
|
let config = load_config(pyproject, quiet)?;
|
||||||
|
println!("{:?}", config.flake8_quotes);
|
||||||
Ok(RawSettings {
|
Ok(RawSettings {
|
||||||
dummy_variable_rgx: match config.dummy_variable_rgx {
|
dummy_variable_rgx: match config.dummy_variable_rgx {
|
||||||
Some(pattern) => Regex::new(&pattern)
|
Some(pattern) => Regex::new(&pattern)
|
||||||
|
|
@ -173,6 +176,11 @@ impl RawSettings {
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|pair| PerFileIgnore::new(pair, project_root))
|
.map(|pair| PerFileIgnore::new(pair, project_root))
|
||||||
.collect(),
|
.collect(),
|
||||||
|
// Plugins
|
||||||
|
flake8_quotes: config
|
||||||
|
.flake8_quotes
|
||||||
|
.map(flake8_quotes::settings::Settings::from_config)
|
||||||
|
.unwrap_or_default(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -186,6 +194,8 @@ pub struct Settings {
|
||||||
pub line_length: usize,
|
pub line_length: usize,
|
||||||
pub per_file_ignores: Vec<PerFileIgnore>,
|
pub per_file_ignores: Vec<PerFileIgnore>,
|
||||||
pub target_version: PythonVersion,
|
pub target_version: PythonVersion,
|
||||||
|
// Plugins
|
||||||
|
pub flake8_quotes: flake8_quotes::settings::Settings,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Settings {
|
impl Settings {
|
||||||
|
|
@ -205,9 +215,10 @@ impl Settings {
|
||||||
enabled,
|
enabled,
|
||||||
exclude: settings.exclude,
|
exclude: settings.exclude,
|
||||||
extend_exclude: settings.extend_exclude,
|
extend_exclude: settings.extend_exclude,
|
||||||
|
flake8_quotes: settings.flake8_quotes,
|
||||||
line_length: settings.line_length,
|
line_length: settings.line_length,
|
||||||
per_file_ignores: settings.per_file_ignores,
|
per_file_ignores: settings.per_file_ignores,
|
||||||
target_version: PythonVersion::Py310,
|
target_version: settings.target_version,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -220,6 +231,7 @@ impl Settings {
|
||||||
line_length: 88,
|
line_length: 88,
|
||||||
per_file_ignores: vec![],
|
per_file_ignores: vec![],
|
||||||
target_version: PythonVersion::Py310,
|
target_version: PythonVersion::Py310,
|
||||||
|
flake8_quotes: Default::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -232,6 +244,7 @@ impl Settings {
|
||||||
line_length: 88,
|
line_length: 88,
|
||||||
per_file_ignores: vec![],
|
per_file_ignores: vec![],
|
||||||
target_version: PythonVersion::Py310,
|
target_version: PythonVersion::Py310,
|
||||||
|
flake8_quotes: Default::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -285,6 +298,9 @@ pub struct CurrentSettings {
|
||||||
pub per_file_ignores: Vec<PerFileIgnore>,
|
pub per_file_ignores: Vec<PerFileIgnore>,
|
||||||
pub select: Vec<CheckCode>,
|
pub select: Vec<CheckCode>,
|
||||||
pub target_version: PythonVersion,
|
pub target_version: PythonVersion,
|
||||||
|
// Plugins
|
||||||
|
pub flake8_quotes: flake8_quotes::settings::Settings,
|
||||||
|
// Non-settings exposed to the user
|
||||||
pub project_root: Option<PathBuf>,
|
pub project_root: Option<PathBuf>,
|
||||||
pub pyproject: Option<PathBuf>,
|
pub pyproject: Option<PathBuf>,
|
||||||
}
|
}
|
||||||
|
|
@ -314,6 +330,7 @@ impl CurrentSettings {
|
||||||
per_file_ignores: settings.per_file_ignores,
|
per_file_ignores: settings.per_file_ignores,
|
||||||
select: settings.select,
|
select: settings.select,
|
||||||
target_version: settings.target_version,
|
target_version: settings.target_version,
|
||||||
|
flake8_quotes: settings.flake8_quotes,
|
||||||
project_root,
|
project_root,
|
||||||
pyproject,
|
pyproject,
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue