Compare commits
8 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b35a804f9d | ||
|
|
e594ed6528 | ||
|
|
197645d90d | ||
|
|
26d3ff5a3a | ||
|
|
0dacf61153 | ||
|
|
a6251360b7 | ||
|
|
2965e2561d | ||
|
|
a19050b8a4 |
@@ -1,6 +1,6 @@
|
||||
repos:
|
||||
- repo: https://github.com/charliermarsh/ruff-pre-commit
|
||||
rev: v0.0.171
|
||||
rev: v0.0.172
|
||||
hooks:
|
||||
- id: ruff
|
||||
|
||||
|
||||
8
Cargo.lock
generated
8
Cargo.lock
generated
@@ -724,7 +724,7 @@ checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80"
|
||||
|
||||
[[package]]
|
||||
name = "flake8-to-ruff"
|
||||
version = "0.0.171-dev.0"
|
||||
version = "0.0.172-dev.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"clap 4.0.29",
|
||||
@@ -1821,7 +1821,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ruff"
|
||||
version = "0.0.171"
|
||||
version = "0.0.172"
|
||||
dependencies = [
|
||||
"annotate-snippets 0.9.1",
|
||||
"anyhow",
|
||||
@@ -1874,7 +1874,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ruff_dev"
|
||||
version = "0.0.171"
|
||||
version = "0.0.172"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"clap 4.0.29",
|
||||
@@ -1892,7 +1892,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ruff_macros"
|
||||
version = "0.0.171"
|
||||
version = "0.0.172"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
||||
@@ -6,7 +6,7 @@ members = [
|
||||
|
||||
[package]
|
||||
name = "ruff"
|
||||
version = "0.0.171"
|
||||
version = "0.0.172"
|
||||
edition = "2021"
|
||||
rust-version = "1.65.0"
|
||||
|
||||
@@ -41,7 +41,7 @@ quick-junit = { version = "0.3.2" }
|
||||
rayon = { version = "1.5.3" }
|
||||
regex = { version = "1.6.0" }
|
||||
ropey = { version = "1.5.0", features = ["cr_lines", "simd"], default-features = false }
|
||||
ruff_macros = { version = "0.0.171", path = "ruff_macros" }
|
||||
ruff_macros = { version = "0.0.172", path = "ruff_macros" }
|
||||
rustc-hash = { version = "1.1.0" }
|
||||
rustpython-ast = { features = ["unparse"], git = "https://github.com/RustPython/RustPython.git", rev = "28f9f65ccc625f00835d84bbb5fba274dce5aa89" }
|
||||
rustpython-common = { git = "https://github.com/RustPython/RustPython.git", rev = "28f9f65ccc625f00835d84bbb5fba274dce5aa89" }
|
||||
|
||||
10
README.md
10
README.md
@@ -147,7 +147,7 @@ Ruff also works with [pre-commit](https://pre-commit.com):
|
||||
```yaml
|
||||
repos:
|
||||
- repo: https://github.com/charliermarsh/ruff-pre-commit
|
||||
rev: v0.0.171
|
||||
rev: v0.0.172
|
||||
hooks:
|
||||
- id: ruff
|
||||
```
|
||||
@@ -438,11 +438,13 @@ For more, see [Pyflakes](https://pypi.org/project/pyflakes/2.5.0/) on PyPI.
|
||||
| F706 | ReturnOutsideFunction | `return` statement outside of a function/method | |
|
||||
| F707 | DefaultExceptNotLast | An `except` block as not the last exception handler | |
|
||||
| F722 | ForwardAnnotationSyntaxError | Syntax error in forward annotation: `...` | |
|
||||
| F811 | RedefinedWhileUnused | Redefinition of unused `...` from line 1 | |
|
||||
| F821 | UndefinedName | Undefined name `...` | |
|
||||
| F822 | UndefinedExport | Undefined name `...` in `__all__` | |
|
||||
| F823 | UndefinedLocal | Local variable `...` referenced before assignment | |
|
||||
| F831 | DuplicateArgumentName | Duplicate argument name in function definition | |
|
||||
| F841 | UnusedVariable | Local variable `...` is assigned to but never used | |
|
||||
| F842 | UnusedAnnotation | Local variable `...` is annotated but never used | |
|
||||
| F901 | RaiseNotImplemented | `raise NotImplemented` should be `raise NotImplementedError` | 🛠 |
|
||||
|
||||
### pycodestyle (E, W)
|
||||
@@ -515,6 +517,7 @@ For more, see [pydocstyle](https://pypi.org/project/pydocstyle/6.1.1/) on PyPI.
|
||||
| D214 | SectionNotOverIndented | Section is over-indented ("Returns") | 🛠 |
|
||||
| D215 | SectionUnderlineNotOverIndented | Section underline is over-indented ("Returns") | 🛠 |
|
||||
| D300 | UsesTripleQuotes | Use """triple double quotes""" | |
|
||||
| D301 | UsesRPrefixForBackslashedContent | Use r""" if any backslashes in a docstring | |
|
||||
| D400 | EndsInPeriod | First line should end with a period | 🛠 |
|
||||
| D402 | NoSignature | First line should not be the function's signature | |
|
||||
| D403 | FirstLineCapitalized | First word of the first line should be properly capitalized | |
|
||||
@@ -1980,6 +1983,10 @@ from .utils import (
|
||||
)
|
||||
```
|
||||
|
||||
Note that this setting is only effective when combined with `combine-as-imports = true`.
|
||||
When `combine-as-imports` isn't enabled, every aliased `import from` will be given its
|
||||
own line, in which case, wrapping is not necessary.
|
||||
|
||||
**Default value**: `false`
|
||||
|
||||
**Type**: `bool`
|
||||
@@ -1989,6 +1996,7 @@ from .utils import (
|
||||
```toml
|
||||
[tool.ruff.isort]
|
||||
force-wrap-aliases = true
|
||||
combine-as-imports = true
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
4
flake8_to_ruff/Cargo.lock
generated
4
flake8_to_ruff/Cargo.lock
generated
@@ -771,7 +771,7 @@ checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80"
|
||||
|
||||
[[package]]
|
||||
name = "flake8_to_ruff"
|
||||
version = "0.0.171"
|
||||
version = "0.0.172"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"clap",
|
||||
@@ -1975,7 +1975,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ruff"
|
||||
version = "0.0.171"
|
||||
version = "0.0.172"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bincode",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "flake8-to-ruff"
|
||||
version = "0.0.171-dev.0"
|
||||
version = "0.0.172-dev.0"
|
||||
edition = "2021"
|
||||
|
||||
[lib]
|
||||
|
||||
@@ -512,6 +512,7 @@ mod tests {
|
||||
CheckCodePrefix::D214,
|
||||
CheckCodePrefix::D215,
|
||||
CheckCodePrefix::D300,
|
||||
CheckCodePrefix::D301,
|
||||
CheckCodePrefix::D400,
|
||||
CheckCodePrefix::D403,
|
||||
CheckCodePrefix::D404,
|
||||
|
||||
@@ -162,6 +162,7 @@ impl DocstringConvention {
|
||||
// CheckCodePrefix::D214,
|
||||
// CheckCodePrefix::D215,
|
||||
CheckCodePrefix::D300,
|
||||
CheckCodePrefix::D301,
|
||||
CheckCodePrefix::D400,
|
||||
CheckCodePrefix::D402,
|
||||
CheckCodePrefix::D403,
|
||||
@@ -209,6 +210,7 @@ impl DocstringConvention {
|
||||
CheckCodePrefix::D214,
|
||||
CheckCodePrefix::D215,
|
||||
CheckCodePrefix::D300,
|
||||
CheckCodePrefix::D301,
|
||||
CheckCodePrefix::D400,
|
||||
// CheckCodePrefix::D402,
|
||||
CheckCodePrefix::D403,
|
||||
@@ -257,6 +259,7 @@ impl DocstringConvention {
|
||||
CheckCodePrefix::D214,
|
||||
// CheckCodePrefix::D215,
|
||||
CheckCodePrefix::D300,
|
||||
CheckCodePrefix::D301,
|
||||
// CheckCodePrefix::D400,
|
||||
CheckCodePrefix::D402,
|
||||
CheckCodePrefix::D403,
|
||||
|
||||
@@ -130,6 +130,12 @@ def x():
|
||||
return val
|
||||
|
||||
|
||||
def x():
|
||||
a = 1
|
||||
print(f"a={a}")
|
||||
return a
|
||||
|
||||
|
||||
# Test cases for using value for assignment then returning it
|
||||
# See:https://github.com/afonasev/flake8-return/issues/47
|
||||
def resolve_from_url(self, url: str) -> dict:
|
||||
|
||||
13
resources/test/fixtures/pyflakes/F842.py
vendored
Normal file
13
resources/test/fixtures/pyflakes/F842.py
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
def f():
|
||||
name: str
|
||||
age: int
|
||||
|
||||
|
||||
class A:
|
||||
name: str
|
||||
age: int
|
||||
|
||||
|
||||
class B:
|
||||
name: str = "Bob"
|
||||
age: int = 18
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "ruff_dev"
|
||||
version = "0.0.171"
|
||||
version = "0.0.172"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "ruff_macros"
|
||||
version = "0.0.171"
|
||||
version = "0.0.172"
|
||||
edition = "2021"
|
||||
|
||||
[lib]
|
||||
|
||||
@@ -2283,7 +2283,6 @@ where
|
||||
self.in_subscript = true;
|
||||
visitor::walk_expr(self, expr);
|
||||
} else {
|
||||
self.in_subscript = true;
|
||||
match typing::match_annotated_subscript(
|
||||
value,
|
||||
&self.from_imports,
|
||||
@@ -2303,8 +2302,7 @@ where
|
||||
// Ex) Annotated[int, "Hello, world!"]
|
||||
SubscriptKind::PEP593AnnotatedSubscript => {
|
||||
// First argument is a type (including forward references); the
|
||||
// rest are arbitrary Python
|
||||
// objects.
|
||||
// rest are arbitrary Python objects.
|
||||
self.visit_expr(value);
|
||||
if let ExprKind::Tuple { elts, ctx } = &slice.node {
|
||||
if let Some(expr) = elts.first() {
|
||||
@@ -2662,8 +2660,7 @@ impl<'a> Checker<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
// TODO(charlie): Don't treat annotations as assignments if there is an existing
|
||||
// value.
|
||||
// Assume the rebound name is used as a global or within a loop.
|
||||
let scope = self.current_scope();
|
||||
let binding = match scope.values.get(&name) {
|
||||
None => binding,
|
||||
@@ -2673,10 +2670,14 @@ impl<'a> Checker<'a> {
|
||||
},
|
||||
};
|
||||
|
||||
self.bindings.push(binding);
|
||||
|
||||
// Don't treat annotations as assignments if there is an existing value
|
||||
// in scope.
|
||||
let scope = &mut self.scopes[*(self.scope_stack.last().expect("No current scope found"))];
|
||||
scope.values.insert(name, index);
|
||||
if !(matches!(binding.kind, BindingKind::Annotation) && scope.values.contains_key(name)) {
|
||||
scope.values.insert(name, index);
|
||||
}
|
||||
|
||||
self.bindings.push(binding);
|
||||
}
|
||||
|
||||
fn handle_node_load(&mut self, expr: &Expr) {
|
||||
@@ -2701,6 +2702,13 @@ impl<'a> Checker<'a> {
|
||||
// Mark the binding as used.
|
||||
self.bindings[*index].used = Some((scope_id, Range::from_located(expr)));
|
||||
|
||||
if matches!(self.bindings[*index].kind, BindingKind::Annotation)
|
||||
&& !self.in_deferred_string_type_definition
|
||||
&& !self.in_deferred_type_definition
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// If the name of the sub-importation is the same as an alias of another
|
||||
// importation and the alias is used, that sub-importation should be
|
||||
// marked as used too.
|
||||
@@ -3112,7 +3120,17 @@ impl<'a> Checker<'a> {
|
||||
while let Some((index, (scopes, _parents))) = self.deferred_assignments.pop() {
|
||||
if self.settings.enabled.contains(&CheckCode::F841) {
|
||||
self.add_checks(
|
||||
pyflakes::checks::unused_variables(
|
||||
pyflakes::checks::unused_variable(
|
||||
&self.scopes[index],
|
||||
&self.bindings,
|
||||
&self.settings.dummy_variable_rgx,
|
||||
)
|
||||
.into_iter(),
|
||||
);
|
||||
}
|
||||
if self.settings.enabled.contains(&CheckCode::F842) {
|
||||
self.add_checks(
|
||||
pyflakes::checks::unused_annotation(
|
||||
&self.scopes[index],
|
||||
&self.bindings,
|
||||
&self.settings.dummy_variable_rgx,
|
||||
@@ -3413,6 +3431,9 @@ impl<'a> Checker<'a> {
|
||||
if self.settings.enabled.contains(&CheckCode::D300) {
|
||||
pydocstyle::plugins::triple_quotes(self, &definition);
|
||||
}
|
||||
if self.settings.enabled.contains(&CheckCode::D301) {
|
||||
pydocstyle::plugins::backslashes(self, &definition);
|
||||
}
|
||||
if self.settings.enabled.contains(&CheckCode::D400) {
|
||||
pydocstyle::plugins::ends_with_period(self, &definition);
|
||||
}
|
||||
|
||||
@@ -93,6 +93,7 @@ pub enum CheckCode {
|
||||
F823,
|
||||
F831,
|
||||
F841,
|
||||
F842,
|
||||
F901,
|
||||
// pylint
|
||||
PLC0414,
|
||||
@@ -243,6 +244,7 @@ pub enum CheckCode {
|
||||
D214,
|
||||
D215,
|
||||
D300,
|
||||
D301,
|
||||
D400,
|
||||
D402,
|
||||
D403,
|
||||
@@ -627,6 +629,7 @@ pub enum CheckKind {
|
||||
TwoStarredExpressions,
|
||||
UndefinedExport(String),
|
||||
UndefinedLocal(String),
|
||||
UnusedAnnotation(String),
|
||||
UndefinedName(String),
|
||||
UnusedImport(String, bool),
|
||||
UnusedVariable(String),
|
||||
@@ -796,6 +799,7 @@ pub enum CheckKind {
|
||||
SectionUnderlineMatchesSectionLength(String),
|
||||
SectionUnderlineNotOverIndented(String),
|
||||
SkipDocstring,
|
||||
UsesRPrefixForBackslashedContent,
|
||||
UsesTripleQuotes,
|
||||
// pep8-naming
|
||||
InvalidClassName(String),
|
||||
@@ -940,6 +944,7 @@ impl CheckCode {
|
||||
CheckCode::F823 => CheckKind::UndefinedLocal("...".to_string()),
|
||||
CheckCode::F831 => CheckKind::DuplicateArgumentName,
|
||||
CheckCode::F841 => CheckKind::UnusedVariable("...".to_string()),
|
||||
CheckCode::F842 => CheckKind::UnusedAnnotation("...".to_string()),
|
||||
CheckCode::F901 => CheckKind::RaiseNotImplemented,
|
||||
// pylint
|
||||
CheckCode::PLC0414 => CheckKind::UselessImportAlias,
|
||||
@@ -1112,6 +1117,7 @@ impl CheckCode {
|
||||
CheckCode::D214 => CheckKind::SectionNotOverIndented("Returns".to_string()),
|
||||
CheckCode::D215 => CheckKind::SectionUnderlineNotOverIndented("Returns".to_string()),
|
||||
CheckCode::D300 => CheckKind::UsesTripleQuotes,
|
||||
CheckCode::D301 => CheckKind::UsesRPrefixForBackslashedContent,
|
||||
CheckCode::D400 => CheckKind::EndsInPeriod,
|
||||
CheckCode::D402 => CheckKind::NoSignature,
|
||||
CheckCode::D403 => CheckKind::FirstLineCapitalized,
|
||||
@@ -1292,6 +1298,7 @@ impl CheckCode {
|
||||
CheckCode::D214 => CheckCategory::Pydocstyle,
|
||||
CheckCode::D215 => CheckCategory::Pydocstyle,
|
||||
CheckCode::D300 => CheckCategory::Pydocstyle,
|
||||
CheckCode::D301 => CheckCategory::Pydocstyle,
|
||||
CheckCode::D400 => CheckCategory::Pydocstyle,
|
||||
CheckCode::D402 => CheckCategory::Pydocstyle,
|
||||
CheckCode::D403 => CheckCategory::Pydocstyle,
|
||||
@@ -1368,6 +1375,7 @@ impl CheckCode {
|
||||
CheckCode::F823 => CheckCategory::Pyflakes,
|
||||
CheckCode::F831 => CheckCategory::Pyflakes,
|
||||
CheckCode::F841 => CheckCategory::Pyflakes,
|
||||
CheckCode::F842 => CheckCategory::Pyflakes,
|
||||
CheckCode::F901 => CheckCategory::Pyflakes,
|
||||
CheckCode::FBT001 => CheckCategory::Flake8BooleanTrap,
|
||||
CheckCode::FBT002 => CheckCategory::Flake8BooleanTrap,
|
||||
@@ -1516,6 +1524,7 @@ impl CheckKind {
|
||||
CheckKind::UndefinedName(_) => &CheckCode::F821,
|
||||
CheckKind::UnusedImport(..) => &CheckCode::F401,
|
||||
CheckKind::UnusedVariable(_) => &CheckCode::F841,
|
||||
CheckKind::UnusedAnnotation(_) => &CheckCode::F842,
|
||||
CheckKind::YieldOutsideFunction(_) => &CheckCode::F704,
|
||||
// pycodestyle warnings
|
||||
CheckKind::NoNewLineAtEndOfFile => &CheckCode::W292,
|
||||
@@ -1685,6 +1694,7 @@ impl CheckKind {
|
||||
CheckKind::SectionUnderlineMatchesSectionLength(_) => &CheckCode::D409,
|
||||
CheckKind::SectionUnderlineNotOverIndented(_) => &CheckCode::D215,
|
||||
CheckKind::SkipDocstring => &CheckCode::D418,
|
||||
CheckKind::UsesRPrefixForBackslashedContent => &CheckCode::D301,
|
||||
CheckKind::UsesTripleQuotes => &CheckCode::D300,
|
||||
// pep8-naming
|
||||
CheckKind::InvalidClassName(_) => &CheckCode::N801,
|
||||
@@ -1902,6 +1912,9 @@ impl CheckKind {
|
||||
CheckKind::UndefinedName(name) => {
|
||||
format!("Undefined name `{name}`")
|
||||
}
|
||||
CheckKind::UnusedAnnotation(name) => {
|
||||
format!("Local variable `{name}` is annotated but never used")
|
||||
}
|
||||
CheckKind::UnusedImport(name, ignore_init) => {
|
||||
if *ignore_init {
|
||||
format!(
|
||||
@@ -1931,8 +1944,8 @@ impl CheckKind {
|
||||
let types = types.join(", ");
|
||||
format!("Merge these isinstance calls: `isinstance({obj}, ({types}))`")
|
||||
}
|
||||
CheckKind::MisplacedComparisonConstant(comprison) => {
|
||||
format!("Comparison should be {comprison}")
|
||||
CheckKind::MisplacedComparisonConstant(comparison) => {
|
||||
format!("Comparison should be {comparison}")
|
||||
}
|
||||
CheckKind::UnnecessaryDirectLambdaCall => "Lambda expression called directly. Execute \
|
||||
the expression inline instead."
|
||||
@@ -2340,6 +2353,9 @@ impl CheckKind {
|
||||
CheckKind::FirstLineCapitalized => {
|
||||
"First word of the first line should be properly capitalized".to_string()
|
||||
}
|
||||
CheckKind::UsesRPrefixForBackslashedContent => {
|
||||
r#"Use r""" if any backslashes in a docstring"#.to_string()
|
||||
}
|
||||
CheckKind::UsesTripleQuotes => r#"Use """triple double quotes""""#.to_string(),
|
||||
CheckKind::MultiLineSummaryFirstLine => {
|
||||
"Multi-line docstring summary should start at the first line".to_string()
|
||||
|
||||
@@ -139,6 +139,7 @@ pub enum CheckCodePrefix {
|
||||
D3,
|
||||
D30,
|
||||
D300,
|
||||
D301,
|
||||
D4,
|
||||
D40,
|
||||
D400,
|
||||
@@ -253,6 +254,7 @@ pub enum CheckCodePrefix {
|
||||
F831,
|
||||
F84,
|
||||
F841,
|
||||
F842,
|
||||
F9,
|
||||
F90,
|
||||
F901,
|
||||
@@ -761,6 +763,7 @@ impl CheckCodePrefix {
|
||||
CheckCode::D214,
|
||||
CheckCode::D215,
|
||||
CheckCode::D300,
|
||||
CheckCode::D301,
|
||||
CheckCode::D400,
|
||||
CheckCode::D402,
|
||||
CheckCode::D403,
|
||||
@@ -863,9 +866,10 @@ impl CheckCodePrefix {
|
||||
CheckCodePrefix::D213 => vec![CheckCode::D213],
|
||||
CheckCodePrefix::D214 => vec![CheckCode::D214],
|
||||
CheckCodePrefix::D215 => vec![CheckCode::D215],
|
||||
CheckCodePrefix::D3 => vec![CheckCode::D300],
|
||||
CheckCodePrefix::D30 => vec![CheckCode::D300],
|
||||
CheckCodePrefix::D3 => vec![CheckCode::D300, CheckCode::D301],
|
||||
CheckCodePrefix::D30 => vec![CheckCode::D300, CheckCode::D301],
|
||||
CheckCodePrefix::D300 => vec![CheckCode::D300],
|
||||
CheckCodePrefix::D301 => vec![CheckCode::D301],
|
||||
CheckCodePrefix::D4 => vec![
|
||||
CheckCode::D400,
|
||||
CheckCode::D402,
|
||||
@@ -1034,6 +1038,7 @@ impl CheckCodePrefix {
|
||||
CheckCode::F823,
|
||||
CheckCode::F831,
|
||||
CheckCode::F841,
|
||||
CheckCode::F842,
|
||||
CheckCode::F901,
|
||||
],
|
||||
CheckCodePrefix::F4 => vec![
|
||||
@@ -1167,6 +1172,7 @@ impl CheckCodePrefix {
|
||||
CheckCode::F823,
|
||||
CheckCode::F831,
|
||||
CheckCode::F841,
|
||||
CheckCode::F842,
|
||||
],
|
||||
CheckCodePrefix::F81 => vec![CheckCode::F811],
|
||||
CheckCodePrefix::F811 => vec![CheckCode::F811],
|
||||
@@ -1176,8 +1182,9 @@ impl CheckCodePrefix {
|
||||
CheckCodePrefix::F823 => vec![CheckCode::F823],
|
||||
CheckCodePrefix::F83 => vec![CheckCode::F831],
|
||||
CheckCodePrefix::F831 => vec![CheckCode::F831],
|
||||
CheckCodePrefix::F84 => vec![CheckCode::F841],
|
||||
CheckCodePrefix::F84 => vec![CheckCode::F841, CheckCode::F842],
|
||||
CheckCodePrefix::F841 => vec![CheckCode::F841],
|
||||
CheckCodePrefix::F842 => vec![CheckCode::F842],
|
||||
CheckCodePrefix::F9 => vec![CheckCode::F901],
|
||||
CheckCodePrefix::F90 => vec![CheckCode::F901],
|
||||
CheckCodePrefix::F901 => vec![CheckCode::F901],
|
||||
@@ -1935,6 +1942,7 @@ impl CheckCodePrefix {
|
||||
CheckCodePrefix::D3 => SuffixLength::One,
|
||||
CheckCodePrefix::D30 => SuffixLength::Two,
|
||||
CheckCodePrefix::D300 => SuffixLength::Three,
|
||||
CheckCodePrefix::D301 => SuffixLength::Three,
|
||||
CheckCodePrefix::D4 => SuffixLength::One,
|
||||
CheckCodePrefix::D40 => SuffixLength::Two,
|
||||
CheckCodePrefix::D400 => SuffixLength::Three,
|
||||
@@ -2049,6 +2057,7 @@ impl CheckCodePrefix {
|
||||
CheckCodePrefix::F831 => SuffixLength::Three,
|
||||
CheckCodePrefix::F84 => SuffixLength::Two,
|
||||
CheckCodePrefix::F841 => SuffixLength::Three,
|
||||
CheckCodePrefix::F842 => SuffixLength::Three,
|
||||
CheckCodePrefix::F9 => SuffixLength::One,
|
||||
CheckCodePrefix::F90 => SuffixLength::Two,
|
||||
CheckCodePrefix::F901 => SuffixLength::Three,
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
pub const TRIPLE_QUOTE_PREFIXES: &[&str] = &[
|
||||
"ur\"\"\"", "ur'''", "u\"\"\"", "u'''", "r\"\"\"", "r'''", "\"\"\"", "'''",
|
||||
"ur\"\"\"", "ur'''", "u\"\"\"", "u'''", "r\"\"\"", "r'''", "UR\"\"\"", "UR'''", "Ur\"\"\"",
|
||||
"Ur'''", "U\"\"\"", "U'''", "uR\"\"\"", "uR'''", "R\"\"\"", "R'''", "\"\"\"", "'''",
|
||||
];
|
||||
|
||||
pub const SINGLE_QUOTE_PREFIXES: &[&str] = &["ur\"", "ur'", "u\"", "u'", "r\"", "r'", "\"", "'"];
|
||||
pub const SINGLE_QUOTE_PREFIXES: &[&str] = &[
|
||||
"ur\"", "ur'", "u\"", "u'", "r\"", "r'", "ur\"", "ur'", "u\"", "u'", "r\"", "r'", "UR\"",
|
||||
"UR'", "Ur\"", "Ur'", "U\"", "U'", "uR\"", "uR'", "R\"", "R'", "\"", "'",
|
||||
];
|
||||
|
||||
@@ -18,6 +18,8 @@ pub struct Stack<'a> {
|
||||
#[derive(Default)]
|
||||
pub struct ReturnVisitor<'a> {
|
||||
pub stack: Stack<'a>,
|
||||
// If we're in an f-string, the location of the defining expression.
|
||||
in_f_string: Option<Location>,
|
||||
}
|
||||
|
||||
impl<'a> ReturnVisitor<'a> {
|
||||
@@ -34,7 +36,7 @@ impl<'a> ReturnVisitor<'a> {
|
||||
.assigns
|
||||
.entry(id)
|
||||
.or_insert_with(Vec::new)
|
||||
.push(expr.location);
|
||||
.push(self.in_f_string.unwrap_or(expr.location));
|
||||
return;
|
||||
}
|
||||
_ => {}
|
||||
@@ -70,7 +72,7 @@ impl<'a> Visitor<'a> for ReturnVisitor<'a> {
|
||||
.refs
|
||||
.entry(id)
|
||||
.or_insert_with(Vec::new)
|
||||
.push(value.location);
|
||||
.push(self.in_f_string.unwrap_or(value.location));
|
||||
}
|
||||
|
||||
visitor::walk_expr(self, value);
|
||||
@@ -111,7 +113,13 @@ impl<'a> Visitor<'a> for ReturnVisitor<'a> {
|
||||
.refs
|
||||
.entry(id)
|
||||
.or_insert_with(Vec::new)
|
||||
.push(expr.location);
|
||||
.push(self.in_f_string.unwrap_or(expr.location));
|
||||
}
|
||||
ExprKind::JoinedStr { .. } => {
|
||||
let prev_in_f_string = self.in_f_string;
|
||||
self.in_f_string = Some(expr.location);
|
||||
visitor::walk_expr(self, expr);
|
||||
self.in_f_string = prev_in_f_string;
|
||||
}
|
||||
_ => visitor::walk_expr(self, expr),
|
||||
}
|
||||
|
||||
@@ -32,11 +32,16 @@ pub struct Options {
|
||||
test_id as test_id
|
||||
)
|
||||
```
|
||||
|
||||
Note that this setting is only effective when combined with `combine-as-imports = true`.
|
||||
When `combine-as-imports` isn't enabled, every aliased `import from` will be given its
|
||||
own line, in which case, wrapping is not necessary.
|
||||
"#,
|
||||
default = r#"false"#,
|
||||
value_type = "bool",
|
||||
example = r#"
|
||||
force-wrap-aliases = true
|
||||
combine-as-imports = true
|
||||
"#
|
||||
)]
|
||||
pub force_wrap_aliases: Option<bool>,
|
||||
|
||||
@@ -4,13 +4,27 @@ use crate::ast::types::Range;
|
||||
use crate::docstrings::constants;
|
||||
use crate::SourceCodeLocator;
|
||||
|
||||
/// Strip the leading and trailing quotes from a docstring.
|
||||
pub fn raw_contents(contents: &str) -> &str {
|
||||
for pattern in constants::TRIPLE_QUOTE_PREFIXES {
|
||||
if contents.starts_with(pattern) {
|
||||
return &contents[pattern.len()..contents.len() - 3];
|
||||
}
|
||||
}
|
||||
for pattern in constants::SINGLE_QUOTE_PREFIXES {
|
||||
if contents.starts_with(pattern) {
|
||||
return &contents[pattern.len()..contents.len() - 1];
|
||||
}
|
||||
}
|
||||
unreachable!("Expected docstring to start with a valid triple- or single-quote prefix")
|
||||
}
|
||||
|
||||
/// Return the leading quote string for a docstring (e.g., `"""`).
|
||||
pub fn leading_quote<'a>(docstring: &Expr, locator: &'a SourceCodeLocator) -> Option<&'a str> {
|
||||
if let Some(first_line) = locator
|
||||
.slice_source_code_range(&Range::from_located(docstring))
|
||||
.lines()
|
||||
.next()
|
||||
.map(str::to_lowercase)
|
||||
{
|
||||
for pattern in constants::TRIPLE_QUOTE_PREFIXES
|
||||
.iter()
|
||||
|
||||
@@ -37,6 +37,7 @@ mod tests {
|
||||
#[test_case(CheckCode::D214, Path::new("sections.py"); "D214")]
|
||||
#[test_case(CheckCode::D215, Path::new("sections.py"); "D215")]
|
||||
#[test_case(CheckCode::D300, Path::new("D.py"); "D300")]
|
||||
#[test_case(CheckCode::D301, Path::new("D.py"); "D301")]
|
||||
#[test_case(CheckCode::D400, Path::new("D.py"); "D400_0")]
|
||||
#[test_case(CheckCode::D400, Path::new("D400.py"); "D400_1")]
|
||||
#[test_case(CheckCode::D402, Path::new("D.py"); "D402")]
|
||||
|
||||
@@ -2,7 +2,7 @@ use itertools::Itertools;
|
||||
use once_cell::sync::Lazy;
|
||||
use regex::Regex;
|
||||
use rustc_hash::FxHashSet;
|
||||
use rustpython_ast::{Constant, ExprKind, Location, StmtKind};
|
||||
use rustpython_ast::{Location, StmtKind};
|
||||
|
||||
use crate::ast::types::Range;
|
||||
use crate::ast::whitespace::LinesWithTrailingNewline;
|
||||
@@ -14,6 +14,7 @@ use crate::docstrings::constants;
|
||||
use crate::docstrings::definition::{Definition, DefinitionKind};
|
||||
use crate::docstrings::sections::{section_contexts, SectionContext};
|
||||
use crate::docstrings::styles::SectionStyle;
|
||||
use crate::pydocstyle::helpers;
|
||||
use crate::pydocstyle::helpers::{leading_quote, logical_line};
|
||||
use crate::visibility::{is_init, is_magic, is_overload, is_override, is_staticmethod, Visibility};
|
||||
|
||||
@@ -123,12 +124,11 @@ pub fn one_liner(checker: &mut Checker, definition: &Definition) {
|
||||
let Some(docstring) = &definition.docstring else {
|
||||
return;
|
||||
};
|
||||
let ExprKind::Constant {
|
||||
value: Constant::Str(string),
|
||||
..
|
||||
} = &docstring.node else {
|
||||
return;
|
||||
};
|
||||
|
||||
let contents = checker
|
||||
.locator
|
||||
.slice_source_code_range(&Range::from_located(docstring));
|
||||
let string = helpers::raw_contents(&contents);
|
||||
|
||||
let mut line_count = 0;
|
||||
let mut non_empty_line_count = 0;
|
||||
@@ -167,12 +167,6 @@ pub fn blank_before_after_function(checker: &mut Checker, definition: &Definitio
|
||||
) = &definition.kind else {
|
||||
return;
|
||||
};
|
||||
let ExprKind::Constant {
|
||||
value: Constant::Str(_),
|
||||
..
|
||||
} = &docstring.node else {
|
||||
return;
|
||||
};
|
||||
|
||||
if checker.settings.enabled.contains(&CheckCode::D201) {
|
||||
let (before, ..) = checker.locator.partition_source_code_at(
|
||||
@@ -255,12 +249,6 @@ pub fn blank_before_after_class(checker: &mut Checker, definition: &Definition)
|
||||
let (DefinitionKind::Class(parent) | DefinitionKind::NestedClass(parent)) = &definition.kind else {
|
||||
return;
|
||||
};
|
||||
let ExprKind::Constant {
|
||||
value: Constant::Str(_),
|
||||
..
|
||||
} = &docstring.node else {
|
||||
return;
|
||||
};
|
||||
|
||||
if checker.settings.enabled.contains(&CheckCode::D203)
|
||||
|| checker.settings.enabled.contains(&CheckCode::D211)
|
||||
@@ -356,12 +344,11 @@ pub fn blank_after_summary(checker: &mut Checker, definition: &Definition) {
|
||||
let Some(docstring) = definition.docstring else {
|
||||
return;
|
||||
};
|
||||
let ExprKind::Constant {
|
||||
value: Constant::Str(string),
|
||||
..
|
||||
} = &docstring.node else {
|
||||
return;
|
||||
};
|
||||
|
||||
let contents = checker
|
||||
.locator
|
||||
.slice_source_code_range(&Range::from_located(docstring));
|
||||
let string = helpers::raw_contents(&contents);
|
||||
|
||||
let mut lines_count = 1;
|
||||
let mut blanks_count = 0;
|
||||
@@ -410,12 +397,11 @@ pub fn indent(checker: &mut Checker, definition: &Definition) {
|
||||
let Some(docstring) = definition.docstring else {
|
||||
return;
|
||||
};
|
||||
let ExprKind::Constant {
|
||||
value: Constant::Str(string),
|
||||
..
|
||||
} = &docstring.node else {
|
||||
return;
|
||||
};
|
||||
|
||||
let contents = checker
|
||||
.locator
|
||||
.slice_source_code_range(&Range::from_located(docstring));
|
||||
let string = helpers::raw_contents(&contents);
|
||||
|
||||
// Split the docstring into lines.
|
||||
let lines: Vec<&str> = LinesWithTrailingNewline::from(string).collect();
|
||||
@@ -550,12 +536,11 @@ pub fn newline_after_last_paragraph(checker: &mut Checker, definition: &Definiti
|
||||
let Some(docstring) = definition.docstring else {
|
||||
return;
|
||||
};
|
||||
let ExprKind::Constant {
|
||||
value: Constant::Str(string),
|
||||
..
|
||||
} = &docstring.node else {
|
||||
return;
|
||||
};
|
||||
|
||||
let contents = checker
|
||||
.locator
|
||||
.slice_source_code_range(&Range::from_located(docstring));
|
||||
let string = helpers::raw_contents(&contents);
|
||||
|
||||
let mut line_count = 0;
|
||||
for line in LinesWithTrailingNewline::from(string) {
|
||||
@@ -563,10 +548,7 @@ pub fn newline_after_last_paragraph(checker: &mut Checker, definition: &Definiti
|
||||
line_count += 1;
|
||||
}
|
||||
if line_count > 1 {
|
||||
let content = checker
|
||||
.locator
|
||||
.slice_source_code_range(&Range::from_located(docstring));
|
||||
if let Some(last_line) = content.lines().last().map(str::trim) {
|
||||
if let Some(last_line) = contents.lines().last().map(str::trim) {
|
||||
if last_line != "\"\"\"" && last_line != "'''" {
|
||||
let mut check = Check::new(
|
||||
CheckKind::NewLineAfterLastParagraph,
|
||||
@@ -599,12 +581,11 @@ pub fn no_surrounding_whitespace(checker: &mut Checker, definition: &Definition)
|
||||
let Some(docstring) = definition.docstring else {
|
||||
return;
|
||||
};
|
||||
let ExprKind::Constant {
|
||||
value: Constant::Str(string),
|
||||
..
|
||||
} = &docstring.node else {
|
||||
return;
|
||||
};
|
||||
|
||||
let contents = checker
|
||||
.locator
|
||||
.slice_source_code_range(&Range::from_located(docstring));
|
||||
let string = helpers::raw_contents(&contents);
|
||||
|
||||
let mut lines = LinesWithTrailingNewline::from(string);
|
||||
let Some(line) = lines.next() else {
|
||||
@@ -650,26 +631,23 @@ pub fn multi_line_summary_start(checker: &mut Checker, definition: &Definition)
|
||||
let Some(docstring) = definition.docstring else {
|
||||
return;
|
||||
};
|
||||
let ExprKind::Constant {
|
||||
value: Constant::Str(string),
|
||||
..
|
||||
} = &docstring.node else
|
||||
{
|
||||
return;
|
||||
};
|
||||
|
||||
let contents = checker
|
||||
.locator
|
||||
.slice_source_code_range(&Range::from_located(docstring));
|
||||
let string = helpers::raw_contents(&contents);
|
||||
|
||||
if LinesWithTrailingNewline::from(string).nth(1).is_none() {
|
||||
return;
|
||||
};
|
||||
let Some(first_line) = checker
|
||||
.locator
|
||||
.slice_source_code_range(&Range::from_located(docstring))
|
||||
let Some(first_line) = contents
|
||||
.lines()
|
||||
.next()
|
||||
.map(str::to_lowercase) else
|
||||
else
|
||||
{
|
||||
return;
|
||||
};
|
||||
if constants::TRIPLE_QUOTE_PREFIXES.contains(&first_line.as_str()) {
|
||||
if constants::TRIPLE_QUOTE_PREFIXES.contains(&first_line) {
|
||||
if checker.settings.enabled.contains(&CheckCode::D212) {
|
||||
checker.add_check(Check::new(
|
||||
CheckKind::MultiLineSummaryFirstLine,
|
||||
@@ -691,15 +669,13 @@ pub fn triple_quotes(checker: &mut Checker, definition: &Definition) {
|
||||
let Some(docstring) = definition.docstring else {
|
||||
return;
|
||||
};
|
||||
let ExprKind::Constant {
|
||||
value: Constant::Str(string),
|
||||
..
|
||||
} = &docstring.node else {
|
||||
return;
|
||||
};
|
||||
let Some(first_line) = checker
|
||||
|
||||
let contents = checker
|
||||
.locator
|
||||
.slice_source_code_range(&Range::from_located(docstring))
|
||||
.slice_source_code_range(&Range::from_located(docstring));
|
||||
let string = helpers::raw_contents(&contents);
|
||||
|
||||
let Some(first_line) = contents
|
||||
.lines()
|
||||
.next()
|
||||
.map(str::to_lowercase) else
|
||||
@@ -725,17 +701,42 @@ pub fn triple_quotes(checker: &mut Checker, definition: &Definition) {
|
||||
}
|
||||
}
|
||||
|
||||
static BACKSLASH_REGEX: Lazy<Regex> = Lazy::new(|| Regex::new(r"\\[^\nuN]").unwrap());
|
||||
|
||||
/// D301
|
||||
pub fn backslashes(checker: &mut Checker, definition: &Definition) {
|
||||
let Some(docstring) = definition.docstring else {
|
||||
return;
|
||||
};
|
||||
|
||||
let contents = checker
|
||||
.locator
|
||||
.slice_source_code_range(&Range::from_located(docstring));
|
||||
|
||||
// Docstring is already raw.
|
||||
if contents.starts_with('r') || contents.starts_with("ur") {
|
||||
return;
|
||||
}
|
||||
|
||||
if BACKSLASH_REGEX.is_match(&contents) {
|
||||
checker.add_check(Check::new(
|
||||
CheckKind::UsesRPrefixForBackslashedContent,
|
||||
Range::from_located(docstring),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
/// D400
|
||||
pub fn ends_with_period(checker: &mut Checker, definition: &Definition) {
|
||||
let Some(docstring) = definition.docstring else {
|
||||
return;
|
||||
};
|
||||
let ExprKind::Constant {
|
||||
value: Constant::Str(string),
|
||||
..
|
||||
} = &docstring.node else {
|
||||
return;
|
||||
};
|
||||
|
||||
let contents = checker
|
||||
.locator
|
||||
.slice_source_code_range(&Range::from_located(docstring));
|
||||
let string = helpers::raw_contents(&contents);
|
||||
|
||||
if let Some(index) = logical_line(string) {
|
||||
let line = string.lines().nth(index).unwrap();
|
||||
let trimmed = line.trim_end();
|
||||
@@ -777,12 +778,12 @@ pub fn no_signature(checker: &mut Checker, definition: &Definition) {
|
||||
let StmtKind::FunctionDef { name, .. } = &parent.node else {
|
||||
return;
|
||||
};
|
||||
let ExprKind::Constant {
|
||||
value: Constant::Str(string),
|
||||
..
|
||||
} = &docstring.node else {
|
||||
return;
|
||||
};
|
||||
|
||||
let contents = checker
|
||||
.locator
|
||||
.slice_source_code_range(&Range::from_located(docstring));
|
||||
let string = helpers::raw_contents(&contents);
|
||||
|
||||
let Some(first_line) = string.lines().next() else {
|
||||
return;
|
||||
};
|
||||
@@ -804,12 +805,11 @@ pub fn capitalized(checker: &mut Checker, definition: &Definition) {
|
||||
let Some(docstring) = definition.docstring else {
|
||||
return
|
||||
};
|
||||
let ExprKind::Constant {
|
||||
value: Constant::Str(string),
|
||||
..
|
||||
} = &docstring.node else {
|
||||
return
|
||||
};
|
||||
let contents = checker
|
||||
.locator
|
||||
.slice_source_code_range(&Range::from_located(docstring));
|
||||
let string = helpers::raw_contents(&contents);
|
||||
|
||||
let Some(first_word) = string.split(' ').next() else {
|
||||
return
|
||||
};
|
||||
@@ -838,12 +838,11 @@ pub fn starts_with_this(checker: &mut Checker, definition: &Definition) {
|
||||
let Some(docstring) = definition.docstring else {
|
||||
return
|
||||
};
|
||||
let ExprKind::Constant {
|
||||
value: Constant::Str(string),
|
||||
..
|
||||
} = &docstring.node else {
|
||||
return
|
||||
};
|
||||
|
||||
let contents = checker
|
||||
.locator
|
||||
.slice_source_code_range(&Range::from_located(docstring));
|
||||
let string = helpers::raw_contents(&contents);
|
||||
|
||||
let trimmed = string.trim();
|
||||
if trimmed.is_empty() {
|
||||
@@ -871,12 +870,12 @@ pub fn ends_with_punctuation(checker: &mut Checker, definition: &Definition) {
|
||||
let Some(docstring) = definition.docstring else {
|
||||
return
|
||||
};
|
||||
let ExprKind::Constant {
|
||||
value: Constant::Str(string),
|
||||
..
|
||||
} = &docstring.node else {
|
||||
return
|
||||
};
|
||||
|
||||
let contents = checker
|
||||
.locator
|
||||
.slice_source_code_range(&Range::from_located(docstring));
|
||||
let string = helpers::raw_contents(&contents);
|
||||
|
||||
if let Some(index) = logical_line(string) {
|
||||
let line = string.lines().nth(index).unwrap();
|
||||
let trimmed = line.trim_end();
|
||||
@@ -930,12 +929,12 @@ pub fn not_empty(checker: &mut Checker, definition: &Definition) -> bool {
|
||||
let Some(docstring) = definition.docstring else {
|
||||
return true;
|
||||
};
|
||||
let ExprKind::Constant {
|
||||
value: Constant::Str(string),
|
||||
..
|
||||
} = &docstring.node else {
|
||||
return true;
|
||||
};
|
||||
|
||||
let contents = checker
|
||||
.locator
|
||||
.slice_source_code_range(&Range::from_located(docstring));
|
||||
let string = helpers::raw_contents(&contents);
|
||||
|
||||
if !string.trim().is_empty() {
|
||||
return true;
|
||||
}
|
||||
@@ -955,12 +954,11 @@ pub fn sections(checker: &mut Checker, definition: &Definition) {
|
||||
let Some(docstring) = definition.docstring else {
|
||||
return
|
||||
};
|
||||
let ExprKind::Constant {
|
||||
value: Constant::Str(string),
|
||||
..
|
||||
} = &docstring.node else {
|
||||
return;
|
||||
};
|
||||
|
||||
let contents = checker
|
||||
.locator
|
||||
.slice_source_code_range(&Range::from_located(docstring));
|
||||
let string = helpers::raw_contents(&contents);
|
||||
|
||||
let lines: Vec<&str> = LinesWithTrailingNewline::from(string).collect();
|
||||
if lines.len() < 2 {
|
||||
@@ -1495,10 +1493,15 @@ fn parameters_section(checker: &mut Checker, definition: &Definition, context: &
|
||||
// Collect the list of arguments documented in the docstring.
|
||||
let mut docstring_args: FxHashSet<&str> = FxHashSet::default();
|
||||
let section_level_indent = whitespace::leading_space(context.line);
|
||||
for i in 1..context.following_lines.len() {
|
||||
let current_line = context.following_lines[i - 1];
|
||||
|
||||
// Join line continuations, then resplit by line.
|
||||
let adjusted_following_lines = context.following_lines.join("\n").replace("\\\n", "");
|
||||
let lines: Vec<&str> = LinesWithTrailingNewline::from(&adjusted_following_lines).collect();
|
||||
|
||||
for i in 1..lines.len() {
|
||||
let current_line = lines[i - 1];
|
||||
let current_leading_space = whitespace::leading_space(current_line);
|
||||
let next_line = context.following_lines[i];
|
||||
let next_line = lines[i];
|
||||
if current_leading_space == section_level_indent
|
||||
&& (whitespace::leading_space(next_line).len() > current_leading_space.len())
|
||||
&& !next_line.trim().is_empty()
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
---
|
||||
source: src/pydocstyle/mod.rs
|
||||
expression: checks
|
||||
---
|
||||
- kind: UsesRPrefixForBackslashedContent
|
||||
location:
|
||||
row: 328
|
||||
column: 4
|
||||
end_location:
|
||||
row: 328
|
||||
column: 16
|
||||
fix: ~
|
||||
- kind: UsesRPrefixForBackslashedContent
|
||||
location:
|
||||
row: 333
|
||||
column: 4
|
||||
end_location:
|
||||
row: 333
|
||||
column: 20
|
||||
fix: ~
|
||||
- kind: UsesRPrefixForBackslashedContent
|
||||
location:
|
||||
row: 338
|
||||
column: 4
|
||||
end_location:
|
||||
row: 338
|
||||
column: 21
|
||||
fix: ~
|
||||
|
||||
@@ -388,7 +388,7 @@ pub fn undefined_local(name: &str, scopes: &[&Scope], bindings: &[Binding]) -> O
|
||||
}
|
||||
|
||||
/// F841
|
||||
pub fn unused_variables(
|
||||
pub fn unused_variable(
|
||||
scope: &Scope,
|
||||
bindings: &[Binding],
|
||||
dummy_variable_rgx: &Regex,
|
||||
@@ -421,6 +421,31 @@ pub fn unused_variables(
|
||||
checks
|
||||
}
|
||||
|
||||
/// F842
|
||||
pub fn unused_annotation(
|
||||
scope: &Scope,
|
||||
bindings: &[Binding],
|
||||
dummy_variable_rgx: &Regex,
|
||||
) -> Vec<Check> {
|
||||
let mut checks: Vec<Check> = vec![];
|
||||
for (name, binding) in scope
|
||||
.values
|
||||
.iter()
|
||||
.map(|(name, index)| (name, &bindings[*index]))
|
||||
{
|
||||
if binding.used.is_none()
|
||||
&& matches!(binding.kind, BindingKind::Annotation)
|
||||
&& !dummy_variable_rgx.is_match(name)
|
||||
{
|
||||
checks.push(Check::new(
|
||||
CheckKind::UnusedAnnotation((*name).to_string()),
|
||||
binding.range,
|
||||
));
|
||||
}
|
||||
}
|
||||
checks
|
||||
}
|
||||
|
||||
/// F707
|
||||
pub fn default_except_not_last(handlers: &[Excepthandler]) -> Option<Check> {
|
||||
for (idx, handler) in handlers.iter().enumerate() {
|
||||
|
||||
1
src/pyflakes/foo.rs
Normal file
1
src/pyflakes/foo.rs
Normal file
@@ -0,0 +1 @@
|
||||
|
||||
1081
src/pyflakes/mod.rs
1081
src/pyflakes/mod.rs
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,23 @@
|
||||
---
|
||||
source: src/pyflakes/mod.rs
|
||||
expression: checks
|
||||
---
|
||||
- kind:
|
||||
UnusedAnnotation: name
|
||||
location:
|
||||
row: 2
|
||||
column: 4
|
||||
end_location:
|
||||
row: 2
|
||||
column: 8
|
||||
fix: ~
|
||||
- kind:
|
||||
UnusedAnnotation: age
|
||||
location:
|
||||
row: 3
|
||||
column: 4
|
||||
end_location:
|
||||
row: 3
|
||||
column: 7
|
||||
fix: ~
|
||||
|
||||
Reference in New Issue
Block a user