Compare commits
24 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0e8c237167 | ||
|
|
960c5e2006 | ||
|
|
9ba17fbf92 | ||
|
|
bfdf972a5d | ||
|
|
0c215365ae | ||
|
|
815284f890 | ||
|
|
6880338a9a | ||
|
|
68b749c67d | ||
|
|
c0fc55b812 | ||
|
|
ba9cf70917 | ||
|
|
f73dfbbfd3 | ||
|
|
62c273cd22 | ||
|
|
938ad9a39e | ||
|
|
14248cb8cb | ||
|
|
3a280039e1 | ||
|
|
4e9e58bdc0 | ||
|
|
926b5494ad | ||
|
|
6717b48ca5 | ||
|
|
f7bb5bc858 | ||
|
|
3e23fd1487 | ||
|
|
01c74e0629 | ||
|
|
1e3cf87f67 | ||
|
|
248447e139 | ||
|
|
95f139583a |
12
.github/workflows/ci.yaml
vendored
12
.github/workflows/ci.yaml
vendored
@@ -117,7 +117,17 @@ jobs:
|
||||
${{ runner.os }}-build-
|
||||
${{ runner.os }}-
|
||||
- run: pip install black[d]==22.12.0
|
||||
- run: cargo test --all
|
||||
- name: Run tests
|
||||
run: |
|
||||
export INSTA_SNAPSHOT_REFERENCES_FILE="$(mktemp)"
|
||||
cargo test --all
|
||||
USED_SNAPSHOTS=$(cat $INSTA_SNAPSHOT_REFERENCES_FILE | xargs realpath --relative-to $PWD)
|
||||
UNUSED_SNAPSHOTS=$(cat <(git ls-files '*.snap') <(echo "$USED_SNAPSHOTS") | sort | uniq -u)
|
||||
if [ ! -z "$UNUSED_SNAPSHOTS" ]; then
|
||||
echo "Found unused snapshots:"
|
||||
echo "$UNUSED_SNAPSHOTS"
|
||||
exit 1
|
||||
fi
|
||||
- run: cargo test --package ruff --test black_compatibility_test -- --ignored
|
||||
|
||||
# TODO(charlie): Re-enable the `wasm-pack` tests.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
repos:
|
||||
- repo: https://github.com/charliermarsh/ruff-pre-commit
|
||||
rev: v0.0.203
|
||||
rev: v0.0.205
|
||||
hooks:
|
||||
- id: ruff
|
||||
|
||||
|
||||
16
Cargo.lock
generated
16
Cargo.lock
generated
@@ -750,7 +750,7 @@ checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80"
|
||||
|
||||
[[package]]
|
||||
name = "flake8-to-ruff"
|
||||
version = "0.0.203-dev.0"
|
||||
version = "0.0.205-dev.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"clap 4.0.32",
|
||||
@@ -1878,7 +1878,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ruff"
|
||||
version = "0.0.203"
|
||||
version = "0.0.205"
|
||||
dependencies = [
|
||||
"annotate-snippets 0.9.1",
|
||||
"anyhow",
|
||||
@@ -1946,7 +1946,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ruff_dev"
|
||||
version = "0.0.203"
|
||||
version = "0.0.205"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"clap 4.0.32",
|
||||
@@ -1967,7 +1967,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ruff_macros"
|
||||
version = "0.0.203"
|
||||
version = "0.0.205"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -2010,7 +2010,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "rustpython-ast"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/RustPython/RustPython.git?rev=68d26955b3e24198a150315e7959719b03709dee#68d26955b3e24198a150315e7959719b03709dee"
|
||||
source = "git+https://github.com/RustPython/RustPython.git?rev=8cb2b8292062adf13bde1b863a9b02c9f0bda3dd#8cb2b8292062adf13bde1b863a9b02c9f0bda3dd"
|
||||
dependencies = [
|
||||
"num-bigint",
|
||||
"rustpython-common",
|
||||
@@ -2020,7 +2020,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "rustpython-common"
|
||||
version = "0.0.0"
|
||||
source = "git+https://github.com/RustPython/RustPython.git?rev=68d26955b3e24198a150315e7959719b03709dee#68d26955b3e24198a150315e7959719b03709dee"
|
||||
source = "git+https://github.com/RustPython/RustPython.git?rev=8cb2b8292062adf13bde1b863a9b02c9f0bda3dd#8cb2b8292062adf13bde1b863a9b02c9f0bda3dd"
|
||||
dependencies = [
|
||||
"ascii",
|
||||
"cfg-if 1.0.0",
|
||||
@@ -2043,7 +2043,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "rustpython-compiler-core"
|
||||
version = "0.1.2"
|
||||
source = "git+https://github.com/RustPython/RustPython.git?rev=68d26955b3e24198a150315e7959719b03709dee#68d26955b3e24198a150315e7959719b03709dee"
|
||||
source = "git+https://github.com/RustPython/RustPython.git?rev=8cb2b8292062adf13bde1b863a9b02c9f0bda3dd#8cb2b8292062adf13bde1b863a9b02c9f0bda3dd"
|
||||
dependencies = [
|
||||
"bincode",
|
||||
"bitflags",
|
||||
@@ -2060,7 +2060,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "rustpython-parser"
|
||||
version = "0.1.2"
|
||||
source = "git+https://github.com/RustPython/RustPython.git?rev=68d26955b3e24198a150315e7959719b03709dee#68d26955b3e24198a150315e7959719b03709dee"
|
||||
source = "git+https://github.com/RustPython/RustPython.git?rev=8cb2b8292062adf13bde1b863a9b02c9f0bda3dd#8cb2b8292062adf13bde1b863a9b02c9f0bda3dd"
|
||||
dependencies = [
|
||||
"ahash",
|
||||
"anyhow",
|
||||
|
||||
10
Cargo.toml
10
Cargo.toml
@@ -6,7 +6,7 @@ members = [
|
||||
|
||||
[package]
|
||||
name = "ruff"
|
||||
version = "0.0.203"
|
||||
version = "0.0.205"
|
||||
authors = ["Charlie Marsh <charlie.r.marsh@gmail.com>"]
|
||||
edition = "2021"
|
||||
rust-version = "1.65.0"
|
||||
@@ -51,11 +51,11 @@ path-absolutize = { version = "3.0.14", features = ["once_cell_cache", "use_unix
|
||||
quick-junit = { version = "0.3.2" }
|
||||
regex = { version = "1.6.0" }
|
||||
ropey = { version = "1.5.0", features = ["cr_lines", "simd"], default-features = false }
|
||||
ruff_macros = { version = "0.0.203", path = "ruff_macros" }
|
||||
ruff_macros = { version = "0.0.205", path = "ruff_macros" }
|
||||
rustc-hash = { version = "1.1.0" }
|
||||
rustpython-ast = { features = ["unparse"], git = "https://github.com/RustPython/RustPython.git", rev = "68d26955b3e24198a150315e7959719b03709dee" }
|
||||
rustpython-common = { git = "https://github.com/RustPython/RustPython.git", rev = "68d26955b3e24198a150315e7959719b03709dee" }
|
||||
rustpython-parser = { features = ["lalrpop"], git = "https://github.com/RustPython/RustPython.git", rev = "68d26955b3e24198a150315e7959719b03709dee" }
|
||||
rustpython-ast = { features = ["unparse"], git = "https://github.com/RustPython/RustPython.git", rev = "8cb2b8292062adf13bde1b863a9b02c9f0bda3dd" }
|
||||
rustpython-common = { git = "https://github.com/RustPython/RustPython.git", rev = "8cb2b8292062adf13bde1b863a9b02c9f0bda3dd" }
|
||||
rustpython-parser = { features = ["lalrpop"], git = "https://github.com/RustPython/RustPython.git", rev = "8cb2b8292062adf13bde1b863a9b02c9f0bda3dd" }
|
||||
schemars = { version = "0.8.11" }
|
||||
semver = { version = "1.0.16" }
|
||||
serde = { version = "1.0.147", features = ["derive"] }
|
||||
|
||||
14
README.md
14
README.md
@@ -169,7 +169,7 @@ Ruff also works with [pre-commit](https://pre-commit.com):
|
||||
```yaml
|
||||
- repo: https://github.com/charliermarsh/ruff-pre-commit
|
||||
# Ruff version.
|
||||
rev: 'v0.0.203'
|
||||
rev: 'v0.0.205'
|
||||
hooks:
|
||||
- id: ruff
|
||||
# Respect `exclude` and `extend-exclude` settings.
|
||||
@@ -384,7 +384,6 @@ Options:
|
||||
Print help information
|
||||
-V, --version
|
||||
Print version information
|
||||
|
||||
```
|
||||
<!-- End auto-generated cli help. -->
|
||||
|
||||
@@ -546,7 +545,7 @@ For more, see [Pyflakes](https://pypi.org/project/pyflakes/2.5.0/) on PyPI.
|
||||
| F621 | ExpressionsInStarAssignment | Too many expressions in star-unpacking assignment | |
|
||||
| F622 | TwoStarredExpressions | Two starred expressions in assignment | |
|
||||
| F631 | AssertTuple | Assert test is a non-empty tuple, which is always `True` | |
|
||||
| F632 | IsLiteral | Use `==` and `!=` to compare constant literals | 🛠 |
|
||||
| F632 | IsLiteral | Use `==` to compare constant literals | 🛠 |
|
||||
| F633 | InvalidPrintSyntax | Use of `>>` is invalid with `print` function | |
|
||||
| F634 | IfTuple | If test is a tuple, which is always `True` | |
|
||||
| F701 | BreakOutsideLoop | `break` outside loop | |
|
||||
@@ -559,7 +558,6 @@ For more, see [Pyflakes](https://pypi.org/project/pyflakes/2.5.0/) on PyPI.
|
||||
| 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` | 🛠 |
|
||||
@@ -579,7 +577,7 @@ For more, see [pycodestyle](https://pypi.org/project/pycodestyle/2.9.1/) on PyPI
|
||||
| E714 | NotIsTest | Test for object identity should be `is not` | 🛠 |
|
||||
| E721 | TypeComparison | Do not compare types, use `isinstance()` | |
|
||||
| E722 | DoNotUseBareExcept | Do not use bare `except` | |
|
||||
| E731 | DoNotAssignLambda | Do not assign a lambda expression, use a def | 🛠 |
|
||||
| E731 | DoNotAssignLambda | Do not assign a `lambda` expression, use a `def` | 🛠 |
|
||||
| E741 | AmbiguousVariableName | Ambiguous variable name: `...` | |
|
||||
| E742 | AmbiguousClassName | Ambiguous class name: `...` | |
|
||||
| E743 | AmbiguousFunctionName | Ambiguous function name: `...` | |
|
||||
@@ -664,7 +662,7 @@ For more, see [pyupgrade](https://pypi.org/project/pyupgrade/3.2.0/) on PyPI.
|
||||
| ---- | ---- | ------- | --- |
|
||||
| UP001 | UselessMetaclassType | `__metaclass__ = type` is implied | 🛠 |
|
||||
| UP003 | TypeOfPrimitive | Use `str` instead of `type(...)` | 🛠 |
|
||||
| UP004 | UselessObjectInheritance | Class `...` inherits from object | 🛠 |
|
||||
| UP004 | UselessObjectInheritance | Class `...` inherits from `object` | 🛠 |
|
||||
| UP005 | DeprecatedUnittestAlias | `assertEquals` is deprecated, use `assertEqual` | 🛠 |
|
||||
| UP006 | UsePEP585Annotation | Use `list` instead of `List` for type annotations | 🛠 |
|
||||
| UP007 | UsePEP604Annotation | Use `X \| Y` for type annotations | 🛠 |
|
||||
@@ -678,7 +676,7 @@ For more, see [pyupgrade](https://pypi.org/project/pyupgrade/3.2.0/) on PyPI.
|
||||
| UP015 | RedundantOpenModes | Unnecessary open mode parameters | 🛠 |
|
||||
| UP016 | RemoveSixCompat | Unnecessary `six` compatibility usage | 🛠 |
|
||||
| UP017 | DatetimeTimezoneUTC | Use `datetime.UTC` alias | 🛠 |
|
||||
| UP018 | NativeLiterals | Unnecessary call to `str` and `bytes` | 🛠 |
|
||||
| UP018 | NativeLiterals | Unnecessary call to `str` | 🛠 |
|
||||
| UP019 | TypingTextStrAlias | `typing.Text` is deprecated, use `str` | 🛠 |
|
||||
| UP020 | OpenAlias | Use builtin `open` | 🛠 |
|
||||
| UP021 | ReplaceUniversalNewlines | `universal_newlines` is deprecated, use `text` | 🛠 |
|
||||
@@ -1019,7 +1017,7 @@ For more, see [Pylint](https://pypi.org/project/pylint/2.15.7/) on PyPI.
|
||||
| ---- | ---- | ------- | --- |
|
||||
| RUF001 | AmbiguousUnicodeCharacterString | String contains ambiguous unicode character '𝐁' (did you mean 'B'?) | 🛠 |
|
||||
| RUF002 | AmbiguousUnicodeCharacterDocstring | Docstring contains ambiguous unicode character '𝐁' (did you mean 'B'?) | 🛠 |
|
||||
| RUF003 | AmbiguousUnicodeCharacterComment | Comment contains ambiguous unicode character '𝐁' (did you mean 'B'?) | |
|
||||
| RUF003 | AmbiguousUnicodeCharacterComment | Comment contains ambiguous unicode character '𝐁' (did you mean 'B'?) | 🛠 |
|
||||
| RUF004 | KeywordArgumentBeforeStarArgument | Keyword argument `...` must come after starred arguments | |
|
||||
| RUF100 | UnusedNOQA | Unused blanket `noqa` directive | 🛠 |
|
||||
|
||||
|
||||
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.203"
|
||||
version = "0.0.205"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"clap",
|
||||
@@ -1975,7 +1975,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ruff"
|
||||
version = "0.0.203"
|
||||
version = "0.0.205"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bincode",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "flake8-to-ruff"
|
||||
version = "0.0.203-dev.0"
|
||||
version = "0.0.205-dev.0"
|
||||
edition = "2021"
|
||||
|
||||
[lib]
|
||||
|
||||
@@ -56,7 +56,9 @@ export default function SourceEditor({
|
||||
.filter((check) => position.startLineNumber === check.location.row)
|
||||
.filter((check) => check.fix)
|
||||
.map((check) => ({
|
||||
title: `Fix ${check.code}`,
|
||||
title: check.fix
|
||||
? `${check.code}: ${check.fix.message}` ?? `Fix ${check.code}`
|
||||
: "Autofix",
|
||||
id: `fix-${check.code}`,
|
||||
kind: "quickfix",
|
||||
edit: check.fix
|
||||
|
||||
@@ -1,5 +1,19 @@
|
||||
[build-system]
|
||||
requires = ["maturin>=0.14,<0.15"]
|
||||
build-backend = "maturin"
|
||||
|
||||
[project]
|
||||
name = "ruff"
|
||||
version = "0.0.205"
|
||||
description = "An extremely fast Python linter, written in Rust."
|
||||
authors = [
|
||||
{ name = "Charlie Marsh", email = "charlie.r.marsh@gmail.com" },
|
||||
]
|
||||
maintainers = [
|
||||
{ name = "Charlie Marsh", email = "charlie.r.marsh@gmail.com" },
|
||||
]
|
||||
requires-python = ">=3.7"
|
||||
license = { file = "LICENSE" }
|
||||
keywords = ["automation", "flake8", "pycodestyle", "pyflakes", "pylint", "clippy"]
|
||||
classifiers = [
|
||||
"Development Status :: 3 - Alpha",
|
||||
@@ -17,24 +31,14 @@ classifiers = [
|
||||
"Topic :: Software Development :: Libraries :: Python Modules",
|
||||
"Topic :: Software Development :: Quality Assurance",
|
||||
]
|
||||
author = "Charlie Marsh"
|
||||
author_email = "charlie.r.marsh@gmail.com"
|
||||
description = "An extremely fast Python linter, written in Rust."
|
||||
requires-python = ">=3.7"
|
||||
|
||||
[project.urls]
|
||||
repository = "https://github.com/charliermarsh/ruff"
|
||||
|
||||
[build-system]
|
||||
requires = ["maturin>=0.14,<0.15"]
|
||||
build-backend = "maturin"
|
||||
urls = { repository = "https://github.com/charliermarsh/ruff-lsp" }
|
||||
|
||||
[tool.maturin]
|
||||
bindings = "bin"
|
||||
strip = true
|
||||
|
||||
[tool.ruff]
|
||||
update-check = true
|
||||
line-length = 88
|
||||
|
||||
[tool.ruff.isort]
|
||||
force-wrap-aliases = true
|
||||
|
||||
@@ -51,3 +51,12 @@ secret == "s3cr3t"
|
||||
token == "s3cr3t"
|
||||
secrete == "s3cr3t"
|
||||
password == safe == "s3cr3t"
|
||||
|
||||
if token == "1\n2":
|
||||
pass
|
||||
|
||||
if token == "3\t4":
|
||||
pass
|
||||
|
||||
if token == "5\r6":
|
||||
pass
|
||||
|
||||
14
resources/test/fixtures/pyflakes/F541.py
vendored
14
resources/test/fixtures/pyflakes/F541.py
vendored
@@ -1,6 +1,8 @@
|
||||
# OK
|
||||
a = "abc"
|
||||
b = f"ghi{'jkl'}"
|
||||
|
||||
# Errors
|
||||
c = f"def"
|
||||
d = f"def" + "ghi"
|
||||
e = (
|
||||
@@ -8,5 +10,17 @@ e = (
|
||||
"ghi"
|
||||
)
|
||||
|
||||
# OK
|
||||
g = f"ghi{123:{45}}"
|
||||
|
||||
# Error
|
||||
h = "x" "y" f"z"
|
||||
|
||||
v = 23.234234
|
||||
|
||||
# OK
|
||||
f"{v:0.2f}"
|
||||
|
||||
# OK (false negatives)
|
||||
f"{v:{f'0.2f'}}"
|
||||
f"{f''}"
|
||||
|
||||
10
resources/test/fixtures/pyflakes/F831.py
vendored
10
resources/test/fixtures/pyflakes/F831.py
vendored
@@ -1,10 +0,0 @@
|
||||
def foo(x: int, y: int, x: int) -> None:
|
||||
pass
|
||||
|
||||
|
||||
def bar(x: int, y: int, *, x: int) -> None:
|
||||
pass
|
||||
|
||||
|
||||
def baz(x: int, y: int, **x: int) -> None:
|
||||
pass
|
||||
@@ -652,8 +652,6 @@
|
||||
"F821",
|
||||
"F822",
|
||||
"F823",
|
||||
"F83",
|
||||
"F831",
|
||||
"F84",
|
||||
"F841",
|
||||
"F842",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "ruff_dev"
|
||||
version = "0.0.203"
|
||||
version = "0.0.205"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
@@ -11,9 +11,9 @@ itertools = { version = "0.10.5" }
|
||||
libcst = { git = "https://github.com/charliermarsh/LibCST", rev = "f2f0b7a487a8725d161fe8b3ed73a6758b21e177" }
|
||||
once_cell = { version = "1.16.0" }
|
||||
ruff = { path = ".." }
|
||||
rustpython-ast = { features = ["unparse"], git = "https://github.com/RustPython/RustPython.git", rev = "68d26955b3e24198a150315e7959719b03709dee" }
|
||||
rustpython-common = { git = "https://github.com/RustPython/RustPython.git", rev = "68d26955b3e24198a150315e7959719b03709dee" }
|
||||
rustpython-parser = { features = ["lalrpop"], git = "https://github.com/RustPython/RustPython.git", rev = "68d26955b3e24198a150315e7959719b03709dee" }
|
||||
rustpython-ast = { features = ["unparse"], git = "https://github.com/RustPython/RustPython.git", rev = "8cb2b8292062adf13bde1b863a9b02c9f0bda3dd" }
|
||||
rustpython-common = { git = "https://github.com/RustPython/RustPython.git", rev = "8cb2b8292062adf13bde1b863a9b02c9f0bda3dd" }
|
||||
rustpython-parser = { features = ["lalrpop"], git = "https://github.com/RustPython/RustPython.git", rev = "8cb2b8292062adf13bde1b863a9b02c9f0bda3dd" }
|
||||
schemars = { version = "0.8.11" }
|
||||
serde_json = {version="1.0.91"}
|
||||
strum = { version = "0.24.1", features = ["strum_macros"] }
|
||||
|
||||
@@ -16,9 +16,13 @@ pub struct Cli {
|
||||
pub(crate) dry_run: bool,
|
||||
}
|
||||
|
||||
fn trim_lines(s: &str) -> String {
|
||||
s.lines().map(str::trim_end).collect::<Vec<_>>().join("\n")
|
||||
}
|
||||
|
||||
pub fn main(cli: &Cli) -> Result<()> {
|
||||
let mut cmd = MainCli::command();
|
||||
let output = cmd.render_help().to_string();
|
||||
let output = trim_lines(cmd.render_help().to_string().trim());
|
||||
|
||||
if cli.dry_run {
|
||||
print!("{output}");
|
||||
|
||||
@@ -22,7 +22,11 @@ pub fn main(cli: &Cli) -> Result<()> {
|
||||
let python_ast = parser::parse_program(&contents, &cli.file.to_string_lossy())?;
|
||||
let locator = SourceCodeLocator::new(&contents);
|
||||
let stylist = SourceCodeStyleDetector::from_contents(&contents, &locator);
|
||||
let mut generator = SourceCodeGenerator::new(stylist.indentation(), stylist.quote());
|
||||
let mut generator = SourceCodeGenerator::new(
|
||||
stylist.indentation(),
|
||||
stylist.quote(),
|
||||
stylist.line_ending(),
|
||||
);
|
||||
generator.unparse_suite(&python_ast);
|
||||
println!("{}", generator.generate()?);
|
||||
Ok(())
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "ruff_macros"
|
||||
version = "0.0.203"
|
||||
version = "0.0.205"
|
||||
edition = "2021"
|
||||
|
||||
[lib]
|
||||
|
||||
@@ -5,7 +5,7 @@ use regex::Regex;
|
||||
use rustc_hash::{FxHashMap, FxHashSet};
|
||||
use rustpython_ast::{
|
||||
Arguments, Constant, Excepthandler, ExcepthandlerKind, Expr, ExprKind, Keyword, KeywordData,
|
||||
Location, Stmt, StmtKind,
|
||||
Located, Location, Stmt, StmtKind,
|
||||
};
|
||||
use rustpython_parser::lexer;
|
||||
use rustpython_parser::lexer::Tok;
|
||||
@@ -395,6 +395,19 @@ pub fn identifier_range(stmt: &Stmt, locator: &SourceCodeLocator) -> Range {
|
||||
Range::from_located(stmt)
|
||||
}
|
||||
|
||||
// Return the ranges of `Name` tokens within a specified node.
|
||||
pub fn find_names<T>(located: &Located<T>, locator: &SourceCodeLocator) -> Vec<Range> {
|
||||
let contents = locator.slice_source_code_range(&Range::from_located(located));
|
||||
lexer::make_tokenizer_located(&contents, located.location)
|
||||
.flatten()
|
||||
.filter(|(_, tok, _)| matches!(tok, Tok::Name { .. }))
|
||||
.map(|(start, _, end)| Range {
|
||||
location: start,
|
||||
end_location: end,
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
/// Return the `Range` of `name` in `Excepthandler`.
|
||||
pub fn excepthandler_name_range(
|
||||
handler: &Excepthandler,
|
||||
@@ -426,6 +439,64 @@ pub fn excepthandler_name_range(
|
||||
}
|
||||
}
|
||||
|
||||
/// Return the `Range` of `except` in `Excepthandler`.
|
||||
pub fn except_range(handler: &Excepthandler, locator: &SourceCodeLocator) -> Range {
|
||||
let ExcepthandlerKind::ExceptHandler { body, type_, .. } = &handler.node;
|
||||
let end = if let Some(type_) = type_ {
|
||||
type_.location
|
||||
} else {
|
||||
body.first()
|
||||
.expect("Expected body to be non-empty")
|
||||
.location
|
||||
};
|
||||
let contents = locator.slice_source_code_range(&Range {
|
||||
location: handler.location,
|
||||
end_location: end,
|
||||
});
|
||||
let range = lexer::make_tokenizer_located(&contents, handler.location)
|
||||
.flatten()
|
||||
.find(|(_, kind, _)| matches!(kind, Tok::Except { .. }))
|
||||
.map(|(location, _, end_location)| Range {
|
||||
location,
|
||||
end_location,
|
||||
})
|
||||
.expect("Failed to find `except` range");
|
||||
range
|
||||
}
|
||||
|
||||
/// Return the `Range` of `else` in `For`, `AsyncFor`, and `While` statements.
|
||||
pub fn else_range(stmt: &Stmt, locator: &SourceCodeLocator) -> Option<Range> {
|
||||
match &stmt.node {
|
||||
StmtKind::For { body, orelse, .. }
|
||||
| StmtKind::AsyncFor { body, orelse, .. }
|
||||
| StmtKind::While { body, orelse, .. }
|
||||
if !orelse.is_empty() =>
|
||||
{
|
||||
let body_end = body
|
||||
.last()
|
||||
.expect("Expected body to be non-empty")
|
||||
.end_location
|
||||
.unwrap();
|
||||
let contents = locator.slice_source_code_range(&Range {
|
||||
location: body_end,
|
||||
end_location: orelse
|
||||
.first()
|
||||
.expect("Expected orelse to be non-empty")
|
||||
.location,
|
||||
});
|
||||
let range = lexer::make_tokenizer_located(&contents, body_end)
|
||||
.flatten()
|
||||
.find(|(_, kind, _)| matches!(kind, Tok::Else))
|
||||
.map(|(location, _, end_location)| Range {
|
||||
location,
|
||||
end_location,
|
||||
});
|
||||
range
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Return `true` if a `Stmt` appears to be part of a multi-statement line, with
|
||||
/// other statements preceding it.
|
||||
pub fn preceded_by_continuation(stmt: &Stmt, locator: &SourceCodeLocator) -> bool {
|
||||
@@ -466,7 +537,9 @@ mod tests {
|
||||
use rustpython_ast::Location;
|
||||
use rustpython_parser::parser;
|
||||
|
||||
use crate::ast::helpers::{identifier_range, match_module_member, match_trailing_content};
|
||||
use crate::ast::helpers::{
|
||||
else_range, identifier_range, match_module_member, match_trailing_content,
|
||||
};
|
||||
use crate::ast::types::Range;
|
||||
use crate::source_code_locator::SourceCodeLocator;
|
||||
|
||||
@@ -738,4 +811,24 @@ class Class():
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_else_range() -> Result<()> {
|
||||
let contents = r#"
|
||||
for x in y:
|
||||
pass
|
||||
else:
|
||||
pass
|
||||
"#
|
||||
.trim();
|
||||
let program = parser::parse_program(contents, "<filename>")?;
|
||||
let stmt = program.first().unwrap();
|
||||
let locator = SourceCodeLocator::new(contents);
|
||||
let range = else_range(stmt, &locator).unwrap();
|
||||
assert_eq!(range.location.row(), 3);
|
||||
assert_eq!(range.location.column(), 0);
|
||||
assert_eq!(range.end_location.row(), 3);
|
||||
assert_eq!(range.end_location.column(), 4);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -87,11 +87,11 @@ pub struct Checker<'a> {
|
||||
deferred_assignments: Vec<DeferralContext<'a>>,
|
||||
// Internal, derivative state.
|
||||
visible_scope: VisibleScope,
|
||||
in_f_string: Option<Range>,
|
||||
in_annotation: bool,
|
||||
in_type_definition: bool,
|
||||
in_deferred_string_type_definition: bool,
|
||||
in_deferred_type_definition: bool,
|
||||
in_f_string: bool,
|
||||
in_literal: bool,
|
||||
in_subscript: bool,
|
||||
seen_import_boundary: bool,
|
||||
@@ -144,11 +144,11 @@ impl<'a> Checker<'a> {
|
||||
modifier: Modifier::Module,
|
||||
visibility: module_visibility(path),
|
||||
},
|
||||
in_f_string: None,
|
||||
in_annotation: false,
|
||||
in_type_definition: false,
|
||||
in_deferred_string_type_definition: false,
|
||||
in_deferred_type_definition: false,
|
||||
in_f_string: false,
|
||||
in_literal: false,
|
||||
in_subscript: false,
|
||||
seen_import_boundary: false,
|
||||
@@ -161,14 +161,7 @@ impl<'a> Checker<'a> {
|
||||
}
|
||||
|
||||
/// Add a `Check` to the `Checker`.
|
||||
pub(crate) fn add_check(&mut self, mut check: Check) {
|
||||
// If we're in an f-string, override the location. RustPython doesn't produce
|
||||
// reliable locations for expressions within f-strings, so we use the
|
||||
// span of the f-string itself as a best-effort default.
|
||||
if let Some(range) = self.in_f_string {
|
||||
check.location = range.location;
|
||||
check.end_location = range.end_location;
|
||||
}
|
||||
pub(crate) fn add_check(&mut self, check: Check) {
|
||||
self.checks.push(check);
|
||||
}
|
||||
|
||||
@@ -184,16 +177,7 @@ impl<'a> Checker<'a> {
|
||||
pub fn patch(&self, code: &CheckCode) -> bool {
|
||||
// TODO(charlie): We can't fix errors in f-strings until RustPython adds
|
||||
// location data.
|
||||
matches!(self.autofix, flags::Autofix::Enabled)
|
||||
&& self.in_f_string.is_none()
|
||||
&& self.settings.fixable.contains(code)
|
||||
}
|
||||
|
||||
/// Return the amended `Range` from a `Located`.
|
||||
pub fn range_for<T>(&self, located: &Located<T>) -> Range {
|
||||
// If we're in an f-string, override the location.
|
||||
self.in_f_string
|
||||
.unwrap_or_else(|| Range::from_located(located))
|
||||
matches!(self.autofix, flags::Autofix::Enabled) && self.settings.fixable.contains(code)
|
||||
}
|
||||
|
||||
/// Return `true` if the `Expr` is a reference to `typing.${target}`.
|
||||
@@ -282,16 +266,17 @@ where
|
||||
match &stmt.node {
|
||||
StmtKind::Global { names } => {
|
||||
let scope_index = *self.scope_stack.last().expect("No current scope found");
|
||||
let ranges = helpers::find_names(stmt, self.locator);
|
||||
if scope_index != GLOBAL_SCOPE_INDEX {
|
||||
// Add the binding to the current scope.
|
||||
let scope = &mut self.scopes[scope_index];
|
||||
let usage = Some((scope.id, Range::from_located(stmt)));
|
||||
for name in names {
|
||||
for (name, range) in names.iter().zip(ranges.iter()) {
|
||||
let index = self.bindings.len();
|
||||
self.bindings.push(Binding {
|
||||
kind: BindingKind::Global,
|
||||
used: usage,
|
||||
range: Range::from_located(stmt),
|
||||
range: *range,
|
||||
source: Some(RefEquality(stmt)),
|
||||
});
|
||||
scope.values.insert(name, index);
|
||||
@@ -302,8 +287,9 @@ where
|
||||
self.add_checks(
|
||||
names
|
||||
.iter()
|
||||
.filter_map(|name| {
|
||||
pycodestyle::checks::ambiguous_variable_name(name, stmt)
|
||||
.zip(ranges.iter())
|
||||
.filter_map(|(name, range)| {
|
||||
pycodestyle::checks::ambiguous_variable_name(name, *range)
|
||||
})
|
||||
.into_iter(),
|
||||
);
|
||||
@@ -311,16 +297,17 @@ where
|
||||
}
|
||||
StmtKind::Nonlocal { names } => {
|
||||
let scope_index = *self.scope_stack.last().expect("No current scope found");
|
||||
let ranges = helpers::find_names(stmt, self.locator);
|
||||
if scope_index != GLOBAL_SCOPE_INDEX {
|
||||
let scope = &mut self.scopes[scope_index];
|
||||
let usage = Some((scope.id, Range::from_located(stmt)));
|
||||
for name in names {
|
||||
for (name, range) in names.iter().zip(ranges.iter()) {
|
||||
// Add a binding to the current scope.
|
||||
let index = self.bindings.len();
|
||||
self.bindings.push(Binding {
|
||||
kind: BindingKind::Nonlocal,
|
||||
used: usage,
|
||||
range: Range::from_located(stmt),
|
||||
range: *range,
|
||||
source: Some(RefEquality(stmt)),
|
||||
});
|
||||
scope.values.insert(name, index);
|
||||
@@ -328,7 +315,7 @@ where
|
||||
|
||||
// Mark the binding in the defining scopes as used too. (Skip the global scope
|
||||
// and the current scope.)
|
||||
for name in names {
|
||||
for (name, range) in names.iter().zip(ranges.iter()) {
|
||||
let mut exists = false;
|
||||
for index in self.scope_stack.iter().skip(1).rev().skip(1) {
|
||||
if let Some(index) = self.scopes[*index].values.get(&name.as_str()) {
|
||||
@@ -342,7 +329,7 @@ where
|
||||
if self.settings.enabled.contains(&CheckCode::PLE0117) {
|
||||
self.add_check(Check::new(
|
||||
CheckKind::NonlocalWithoutBinding(name.to_string()),
|
||||
Range::from_located(stmt),
|
||||
*range,
|
||||
));
|
||||
}
|
||||
}
|
||||
@@ -353,8 +340,9 @@ where
|
||||
self.add_checks(
|
||||
names
|
||||
.iter()
|
||||
.filter_map(|name| {
|
||||
pycodestyle::checks::ambiguous_variable_name(name, stmt)
|
||||
.zip(ranges.iter())
|
||||
.filter_map(|(name, range)| {
|
||||
pycodestyle::checks::ambiguous_variable_name(name, *range)
|
||||
})
|
||||
.into_iter(),
|
||||
);
|
||||
@@ -550,7 +538,7 @@ where
|
||||
Binding {
|
||||
kind: BindingKind::FunctionDefinition,
|
||||
used: None,
|
||||
range: Range::from_located(stmt),
|
||||
range: helpers::identifier_range(stmt, self.locator),
|
||||
source: Some(self.current_stmt().clone()),
|
||||
},
|
||||
);
|
||||
@@ -600,9 +588,12 @@ where
|
||||
}
|
||||
|
||||
if self.settings.enabled.contains(&CheckCode::N818) {
|
||||
if let Some(check) =
|
||||
pep8_naming::checks::error_suffix_on_exception_name(stmt, bases, name)
|
||||
{
|
||||
if let Some(check) = pep8_naming::checks::error_suffix_on_exception_name(
|
||||
stmt,
|
||||
bases,
|
||||
name,
|
||||
self.locator,
|
||||
) {
|
||||
self.add_check(check);
|
||||
}
|
||||
}
|
||||
@@ -1186,7 +1177,9 @@ where
|
||||
}
|
||||
StmtKind::Try { handlers, .. } => {
|
||||
if self.settings.enabled.contains(&CheckCode::F707) {
|
||||
if let Some(check) = pyflakes::checks::default_except_not_last(handlers) {
|
||||
if let Some(check) =
|
||||
pyflakes::checks::default_except_not_last(handlers, self.locator)
|
||||
{
|
||||
self.add_check(check);
|
||||
}
|
||||
}
|
||||
@@ -1430,7 +1423,7 @@ where
|
||||
Binding {
|
||||
kind: BindingKind::ClassDefinition,
|
||||
used: None,
|
||||
range: Range::from_located(stmt),
|
||||
range: helpers::identifier_range(stmt, self.locator),
|
||||
source: Some(self.current_stmt().clone()),
|
||||
},
|
||||
);
|
||||
@@ -1554,9 +1547,10 @@ where
|
||||
}
|
||||
ExprContext::Store => {
|
||||
if self.settings.enabled.contains(&CheckCode::E741) {
|
||||
if let Some(check) =
|
||||
pycodestyle::checks::ambiguous_variable_name(id, expr)
|
||||
{
|
||||
if let Some(check) = pycodestyle::checks::ambiguous_variable_name(
|
||||
id,
|
||||
Range::from_located(expr),
|
||||
) {
|
||||
self.add_check(check);
|
||||
}
|
||||
}
|
||||
@@ -1727,7 +1721,7 @@ where
|
||||
if self.settings.enabled.contains(&CheckCode::T201)
|
||||
|| self.settings.enabled.contains(&CheckCode::T203)
|
||||
{
|
||||
flake8_print::plugins::print_call(self, expr, func, keywords);
|
||||
flake8_print::plugins::print_call(self, func, keywords);
|
||||
}
|
||||
|
||||
// flake8-bugbear
|
||||
@@ -2165,11 +2159,12 @@ where
|
||||
}
|
||||
}
|
||||
ExprKind::JoinedStr { values } => {
|
||||
if self.settings.enabled.contains(&CheckCode::F541) {
|
||||
if self.in_f_string.is_none()
|
||||
&& !values
|
||||
.iter()
|
||||
.any(|value| matches!(value.node, ExprKind::FormattedValue { .. }))
|
||||
// Conversion flags are parsed as f-strings without placeholders, so skip
|
||||
// nested f-strings, which would lead to false positives.
|
||||
if !self.in_f_string && self.settings.enabled.contains(&CheckCode::F541) {
|
||||
if !values
|
||||
.iter()
|
||||
.any(|value| matches!(value.node, ExprKind::FormattedValue { .. }))
|
||||
{
|
||||
self.add_check(Check::new(
|
||||
CheckKind::FStringMissingPlaceholders,
|
||||
@@ -2177,7 +2172,6 @@ where
|
||||
));
|
||||
}
|
||||
}
|
||||
self.in_f_string = Some(Range::from_located(expr));
|
||||
}
|
||||
ExprKind::BinOp {
|
||||
left,
|
||||
@@ -2670,6 +2664,11 @@ where
|
||||
}
|
||||
self.in_subscript = prev_in_subscript;
|
||||
}
|
||||
ExprKind::JoinedStr { .. } => {
|
||||
self.in_f_string = true;
|
||||
visitor::walk_expr(self, expr);
|
||||
self.in_f_string = prev_in_f_string;
|
||||
}
|
||||
_ => visitor::walk_expr(self, expr),
|
||||
}
|
||||
|
||||
@@ -2701,7 +2700,8 @@ where
|
||||
if let Some(check) = pycodestyle::checks::do_not_use_bare_except(
|
||||
type_.as_deref(),
|
||||
body,
|
||||
Range::from_located(excepthandler),
|
||||
excepthandler,
|
||||
self.locator,
|
||||
) {
|
||||
self.add_check(check);
|
||||
}
|
||||
@@ -2720,9 +2720,11 @@ where
|
||||
match name {
|
||||
Some(name) => {
|
||||
if self.settings.enabled.contains(&CheckCode::E741) {
|
||||
if let Some(check) =
|
||||
pycodestyle::checks::ambiguous_variable_name(name, excepthandler)
|
||||
{
|
||||
if let Some(check) = pycodestyle::checks::ambiguous_variable_name(
|
||||
name,
|
||||
helpers::excepthandler_name_range(excepthandler, self.locator)
|
||||
.expect("Failed to find `name` range"),
|
||||
) {
|
||||
self.add_check(check);
|
||||
}
|
||||
}
|
||||
@@ -2789,10 +2791,6 @@ where
|
||||
}
|
||||
|
||||
fn visit_arguments(&mut self, arguments: &'b Arguments) {
|
||||
if self.settings.enabled.contains(&CheckCode::F831) {
|
||||
self.checks
|
||||
.extend(pyflakes::checks::duplicate_arguments(arguments));
|
||||
}
|
||||
if self.settings.enabled.contains(&CheckCode::B006) {
|
||||
flake8_bugbear::plugins::mutable_argument_default(self, arguments);
|
||||
}
|
||||
@@ -2843,7 +2841,10 @@ where
|
||||
);
|
||||
|
||||
if self.settings.enabled.contains(&CheckCode::E741) {
|
||||
if let Some(check) = pycodestyle::checks::ambiguous_variable_name(&arg.node.arg, arg) {
|
||||
if let Some(check) = pycodestyle::checks::ambiguous_variable_name(
|
||||
&arg.node.arg,
|
||||
Range::from_located(arg),
|
||||
) {
|
||||
self.add_check(check);
|
||||
}
|
||||
}
|
||||
@@ -3735,9 +3736,10 @@ impl<'a> Checker<'a> {
|
||||
None
|
||||
};
|
||||
|
||||
let multiple = unused_imports.len() > 1;
|
||||
for (full_name, range) in unused_imports {
|
||||
let mut check = Check::new(
|
||||
CheckKind::UnusedImport(full_name.clone(), ignore_init),
|
||||
CheckKind::UnusedImport(full_name.clone(), ignore_init, multiple),
|
||||
*range,
|
||||
);
|
||||
if matches!(child.node, StmtKind::ImportFrom { .. })
|
||||
@@ -3756,9 +3758,10 @@ impl<'a> Checker<'a> {
|
||||
.sorted_by_key(|((defined_by, _), _)| defined_by.0.location)
|
||||
{
|
||||
let child = defined_by.0;
|
||||
let multiple = unused_imports.len() > 1;
|
||||
for (full_name, range) in unused_imports {
|
||||
let mut check = Check::new(
|
||||
CheckKind::UnusedImport(full_name.clone(), ignore_init),
|
||||
CheckKind::UnusedImport(full_name.clone(), ignore_init, multiple),
|
||||
*range,
|
||||
);
|
||||
if matches!(child.node, StmtKind::ImportFrom { .. })
|
||||
|
||||
402
src/checks.rs
402
src/checks.rs
@@ -3,6 +3,7 @@ use std::fmt;
|
||||
use itertools::Itertools;
|
||||
use once_cell::sync::Lazy;
|
||||
use rustc_hash::FxHashMap;
|
||||
use rustpython_ast::Cmpop;
|
||||
use rustpython_parser::ast::Location;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use strum_macros::{AsRefStr, Display, EnumIter, EnumString};
|
||||
@@ -91,7 +92,6 @@ pub enum CheckCode {
|
||||
F821,
|
||||
F822,
|
||||
F823,
|
||||
F831,
|
||||
F841,
|
||||
F842,
|
||||
F901,
|
||||
@@ -618,11 +618,37 @@ pub enum LintSource {
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub enum RejectedCmpop {
|
||||
pub enum EqCmpop {
|
||||
Eq,
|
||||
NotEq,
|
||||
}
|
||||
|
||||
impl From<&Cmpop> for EqCmpop {
|
||||
fn from(cmpop: &Cmpop) -> Self {
|
||||
match cmpop {
|
||||
Cmpop::Eq => EqCmpop::Eq,
|
||||
Cmpop::NotEq => EqCmpop::NotEq,
|
||||
_ => unreachable!("Expected Cmpop::Eq | Cmpop::NotEq"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub enum IsCmpop {
|
||||
Is,
|
||||
IsNot,
|
||||
}
|
||||
|
||||
impl From<&Cmpop> for IsCmpop {
|
||||
fn from(cmpop: &Cmpop) -> Self {
|
||||
match cmpop {
|
||||
Cmpop::Is => IsCmpop::Is,
|
||||
Cmpop::IsNot => IsCmpop::IsNot,
|
||||
_ => unreachable!("Expected Cmpop::Is | Cmpop::IsNot"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub enum DeferralKeyword {
|
||||
Yield,
|
||||
@@ -655,6 +681,21 @@ impl fmt::Display for Branch {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub enum LiteralType {
|
||||
Str,
|
||||
Bytes,
|
||||
}
|
||||
|
||||
impl fmt::Display for LiteralType {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self {
|
||||
LiteralType::Str => fmt.write_str("str"),
|
||||
LiteralType::Bytes => fmt.write_str("bytes"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub struct UnusedCodes {
|
||||
pub unknown: Vec<String>,
|
||||
@@ -668,17 +709,17 @@ pub enum CheckKind {
|
||||
AmbiguousClassName(String),
|
||||
AmbiguousFunctionName(String),
|
||||
AmbiguousVariableName(String),
|
||||
DoNotAssignLambda,
|
||||
DoNotAssignLambda(String),
|
||||
DoNotUseBareExcept,
|
||||
IOError(String),
|
||||
LineTooLong(usize, usize),
|
||||
ModuleImportNotAtTopOfFile,
|
||||
MultipleImportsOnOneLine,
|
||||
NoneComparison(RejectedCmpop),
|
||||
NoneComparison(EqCmpop),
|
||||
NotInTest,
|
||||
NotIsTest,
|
||||
SyntaxError(String),
|
||||
TrueFalseComparison(bool, RejectedCmpop),
|
||||
TrueFalseComparison(bool, EqCmpop),
|
||||
TypeComparison,
|
||||
// pycodestyle warnings
|
||||
NoNewLineAtEndOfFile,
|
||||
@@ -688,7 +729,6 @@ pub enum CheckKind {
|
||||
BreakOutsideLoop,
|
||||
ContinueOutsideLoop,
|
||||
DefaultExceptNotLast,
|
||||
DuplicateArgumentName,
|
||||
ExpressionsInStarAssignment,
|
||||
FStringMissingPlaceholders,
|
||||
ForwardAnnotationSyntaxError(String),
|
||||
@@ -699,7 +739,7 @@ pub enum CheckKind {
|
||||
ImportStarUsage(String, Vec<String>),
|
||||
ImportStarUsed(String),
|
||||
InvalidPrintSyntax,
|
||||
IsLiteral,
|
||||
IsLiteral(IsCmpop),
|
||||
LateFutureImport,
|
||||
MultiValueRepeatedKeyLiteral,
|
||||
MultiValueRepeatedKeyVariable(String),
|
||||
@@ -725,7 +765,7 @@ pub enum CheckKind {
|
||||
UndefinedLocal(String),
|
||||
UnusedAnnotation(String),
|
||||
UndefinedName(String),
|
||||
UnusedImport(String, bool),
|
||||
UnusedImport(String, bool, bool),
|
||||
UnusedVariable(String),
|
||||
YieldOutsideFunction(DeferralKeyword),
|
||||
// pylint
|
||||
@@ -859,10 +899,10 @@ pub enum CheckKind {
|
||||
UnnecessaryEncodeUTF8,
|
||||
ConvertTypedDictFunctionalToClass(String),
|
||||
ConvertNamedTupleFunctionalToClass(String),
|
||||
RedundantOpenModes,
|
||||
RedundantOpenModes(Option<String>),
|
||||
RemoveSixCompat,
|
||||
DatetimeTimezoneUTC,
|
||||
NativeLiterals,
|
||||
NativeLiterals(LiteralType),
|
||||
OpenAlias,
|
||||
ReplaceUniversalNewlines,
|
||||
ReplaceStdoutStderr,
|
||||
@@ -1030,13 +1070,13 @@ impl CheckCode {
|
||||
CheckCode::E401 => CheckKind::MultipleImportsOnOneLine,
|
||||
CheckCode::E402 => CheckKind::ModuleImportNotAtTopOfFile,
|
||||
CheckCode::E501 => CheckKind::LineTooLong(89, 88),
|
||||
CheckCode::E711 => CheckKind::NoneComparison(RejectedCmpop::Eq),
|
||||
CheckCode::E712 => CheckKind::TrueFalseComparison(true, RejectedCmpop::Eq),
|
||||
CheckCode::E711 => CheckKind::NoneComparison(EqCmpop::Eq),
|
||||
CheckCode::E712 => CheckKind::TrueFalseComparison(true, EqCmpop::Eq),
|
||||
CheckCode::E713 => CheckKind::NotInTest,
|
||||
CheckCode::E714 => CheckKind::NotIsTest,
|
||||
CheckCode::E721 => CheckKind::TypeComparison,
|
||||
CheckCode::E722 => CheckKind::DoNotUseBareExcept,
|
||||
CheckCode::E731 => CheckKind::DoNotAssignLambda,
|
||||
CheckCode::E731 => CheckKind::DoNotAssignLambda("...".to_string()),
|
||||
CheckCode::E741 => CheckKind::AmbiguousVariableName("...".to_string()),
|
||||
CheckCode::E742 => CheckKind::AmbiguousClassName("...".to_string()),
|
||||
CheckCode::E743 => CheckKind::AmbiguousFunctionName("...".to_string()),
|
||||
@@ -1046,7 +1086,7 @@ impl CheckCode {
|
||||
CheckCode::W292 => CheckKind::NoNewLineAtEndOfFile,
|
||||
CheckCode::W605 => CheckKind::InvalidEscapeSequence('c'),
|
||||
// pyflakes
|
||||
CheckCode::F401 => CheckKind::UnusedImport("...".to_string(), false),
|
||||
CheckCode::F401 => CheckKind::UnusedImport("...".to_string(), false, false),
|
||||
CheckCode::F402 => CheckKind::ImportShadowedByLoopVar("...".to_string(), 1),
|
||||
CheckCode::F403 => CheckKind::ImportStarUsed("...".to_string()),
|
||||
CheckCode::F404 => CheckKind::LateFutureImport,
|
||||
@@ -1079,7 +1119,7 @@ impl CheckCode {
|
||||
CheckCode::F621 => CheckKind::ExpressionsInStarAssignment,
|
||||
CheckCode::F622 => CheckKind::TwoStarredExpressions,
|
||||
CheckCode::F631 => CheckKind::AssertTuple,
|
||||
CheckCode::F632 => CheckKind::IsLiteral,
|
||||
CheckCode::F632 => CheckKind::IsLiteral(IsCmpop::Is),
|
||||
CheckCode::F633 => CheckKind::InvalidPrintSyntax,
|
||||
CheckCode::F634 => CheckKind::IfTuple,
|
||||
CheckCode::F701 => CheckKind::BreakOutsideLoop,
|
||||
@@ -1092,7 +1132,6 @@ impl CheckCode {
|
||||
CheckCode::F821 => CheckKind::UndefinedName("...".to_string()),
|
||||
CheckCode::F822 => CheckKind::UndefinedExport("...".to_string()),
|
||||
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,
|
||||
@@ -1253,10 +1292,10 @@ impl CheckCode {
|
||||
CheckCode::UP012 => CheckKind::UnnecessaryEncodeUTF8,
|
||||
CheckCode::UP013 => CheckKind::ConvertTypedDictFunctionalToClass("...".to_string()),
|
||||
CheckCode::UP014 => CheckKind::ConvertNamedTupleFunctionalToClass("...".to_string()),
|
||||
CheckCode::UP015 => CheckKind::RedundantOpenModes,
|
||||
CheckCode::UP015 => CheckKind::RedundantOpenModes(None),
|
||||
CheckCode::UP016 => CheckKind::RemoveSixCompat,
|
||||
CheckCode::UP017 => CheckKind::DatetimeTimezoneUTC,
|
||||
CheckCode::UP018 => CheckKind::NativeLiterals,
|
||||
CheckCode::UP018 => CheckKind::NativeLiterals(LiteralType::Str),
|
||||
CheckCode::UP019 => CheckKind::TypingTextStrAlias,
|
||||
CheckCode::UP020 => CheckKind::OpenAlias,
|
||||
CheckCode::UP021 => CheckKind::ReplaceUniversalNewlines,
|
||||
@@ -1589,7 +1628,6 @@ impl CheckCode {
|
||||
CheckCode::F821 => CheckCategory::Pyflakes,
|
||||
CheckCode::F822 => CheckCategory::Pyflakes,
|
||||
CheckCode::F823 => CheckCategory::Pyflakes,
|
||||
CheckCode::F831 => CheckCategory::Pyflakes,
|
||||
CheckCode::F841 => CheckCategory::Pyflakes,
|
||||
CheckCode::F842 => CheckCategory::Pyflakes,
|
||||
CheckCode::F901 => CheckCategory::Pyflakes,
|
||||
@@ -1724,9 +1762,8 @@ impl CheckKind {
|
||||
CheckKind::BreakOutsideLoop => &CheckCode::F701,
|
||||
CheckKind::ContinueOutsideLoop => &CheckCode::F702,
|
||||
CheckKind::DefaultExceptNotLast => &CheckCode::F707,
|
||||
CheckKind::DoNotAssignLambda => &CheckCode::E731,
|
||||
CheckKind::DoNotAssignLambda(..) => &CheckCode::E731,
|
||||
CheckKind::DoNotUseBareExcept => &CheckCode::E722,
|
||||
CheckKind::DuplicateArgumentName => &CheckCode::F831,
|
||||
CheckKind::FStringMissingPlaceholders => &CheckCode::F541,
|
||||
CheckKind::ForwardAnnotationSyntaxError(..) => &CheckCode::F722,
|
||||
CheckKind::FutureFeatureNotDefined(..) => &CheckCode::F407,
|
||||
@@ -1737,7 +1774,7 @@ impl CheckKind {
|
||||
CheckKind::ImportStarUsage(..) => &CheckCode::F405,
|
||||
CheckKind::ImportStarUsed(..) => &CheckCode::F403,
|
||||
CheckKind::InvalidPrintSyntax => &CheckCode::F633,
|
||||
CheckKind::IsLiteral => &CheckCode::F632,
|
||||
CheckKind::IsLiteral(..) => &CheckCode::F632,
|
||||
CheckKind::LateFutureImport => &CheckCode::F404,
|
||||
CheckKind::LineTooLong(..) => &CheckCode::E501,
|
||||
CheckKind::MultipleImportsOnOneLine => &CheckCode::E401,
|
||||
@@ -1909,10 +1946,10 @@ impl CheckKind {
|
||||
CheckKind::UnnecessaryEncodeUTF8 => &CheckCode::UP012,
|
||||
CheckKind::ConvertTypedDictFunctionalToClass(..) => &CheckCode::UP013,
|
||||
CheckKind::ConvertNamedTupleFunctionalToClass(..) => &CheckCode::UP014,
|
||||
CheckKind::RedundantOpenModes => &CheckCode::UP015,
|
||||
CheckKind::RedundantOpenModes(..) => &CheckCode::UP015,
|
||||
CheckKind::RemoveSixCompat => &CheckCode::UP016,
|
||||
CheckKind::DatetimeTimezoneUTC => &CheckCode::UP017,
|
||||
CheckKind::NativeLiterals => &CheckCode::UP018,
|
||||
CheckKind::NativeLiterals(..) => &CheckCode::UP018,
|
||||
CheckKind::TypingTextStrAlias => &CheckCode::UP019,
|
||||
CheckKind::OpenAlias => &CheckCode::UP020,
|
||||
CheckKind::ReplaceUniversalNewlines => &CheckCode::UP021,
|
||||
@@ -2068,13 +2105,10 @@ impl CheckKind {
|
||||
CheckKind::DefaultExceptNotLast => {
|
||||
"An `except` block as not the last exception handler".to_string()
|
||||
}
|
||||
CheckKind::DoNotAssignLambda => {
|
||||
"Do not assign a lambda expression, use a def".to_string()
|
||||
CheckKind::DoNotAssignLambda(..) => {
|
||||
"Do not assign a `lambda` expression, use a `def`".to_string()
|
||||
}
|
||||
CheckKind::DoNotUseBareExcept => "Do not use bare `except`".to_string(),
|
||||
CheckKind::DuplicateArgumentName => {
|
||||
"Duplicate argument name in function definition".to_string()
|
||||
}
|
||||
CheckKind::ForwardAnnotationSyntaxError(body) => {
|
||||
format!("Syntax error in forward annotation: `{body}`")
|
||||
}
|
||||
@@ -2105,7 +2139,10 @@ impl CheckKind {
|
||||
.join(", ");
|
||||
format!("`{name}` may be undefined, or defined from star imports: {sources}")
|
||||
}
|
||||
CheckKind::IsLiteral => "Use `==` and `!=` to compare constant literals".to_string(),
|
||||
CheckKind::IsLiteral(cmpop) => match cmpop {
|
||||
IsCmpop::Is => "Use `==` to compare constant literals".to_string(),
|
||||
IsCmpop::IsNot => "Use `!=` to compare constant literals".to_string(),
|
||||
},
|
||||
CheckKind::LateFutureImport => {
|
||||
"`from __future__` imports must occur at the beginning of the file".to_string()
|
||||
}
|
||||
@@ -2123,10 +2160,8 @@ impl CheckKind {
|
||||
format!("Dictionary key `{name}` repeated")
|
||||
}
|
||||
CheckKind::NoneComparison(op) => match op {
|
||||
RejectedCmpop::Eq => "Comparison to `None` should be `cond is None`".to_string(),
|
||||
RejectedCmpop::NotEq => {
|
||||
"Comparison to `None` should be `cond is not None`".to_string()
|
||||
}
|
||||
EqCmpop::Eq => "Comparison to `None` should be `cond is None`".to_string(),
|
||||
EqCmpop::NotEq => "Comparison to `None` should be `cond is not None`".to_string(),
|
||||
},
|
||||
CheckKind::NotInTest => "Test for membership should be `not in`".to_string(),
|
||||
CheckKind::NotIsTest => "Test for object identity should be `is not`".to_string(),
|
||||
@@ -2190,16 +2225,16 @@ impl CheckKind {
|
||||
CheckKind::ExpressionsInStarAssignment => {
|
||||
"Too many expressions in star-unpacking assignment".to_string()
|
||||
}
|
||||
CheckKind::TrueFalseComparison(true, RejectedCmpop::Eq) => {
|
||||
CheckKind::TrueFalseComparison(true, EqCmpop::Eq) => {
|
||||
"Comparison to `True` should be `cond is True`".to_string()
|
||||
}
|
||||
CheckKind::TrueFalseComparison(true, RejectedCmpop::NotEq) => {
|
||||
CheckKind::TrueFalseComparison(true, EqCmpop::NotEq) => {
|
||||
"Comparison to `True` should be `cond is not True`".to_string()
|
||||
}
|
||||
CheckKind::TrueFalseComparison(false, RejectedCmpop::Eq) => {
|
||||
CheckKind::TrueFalseComparison(false, EqCmpop::Eq) => {
|
||||
"Comparison to `False` should be `cond is False`".to_string()
|
||||
}
|
||||
CheckKind::TrueFalseComparison(false, RejectedCmpop::NotEq) => {
|
||||
CheckKind::TrueFalseComparison(false, EqCmpop::NotEq) => {
|
||||
"Comparison to `False` should be `cond is not False`".to_string()
|
||||
}
|
||||
CheckKind::TwoStarredExpressions => "Two starred expressions in assignment".to_string(),
|
||||
@@ -2216,7 +2251,7 @@ impl CheckKind {
|
||||
CheckKind::UnusedAnnotation(name) => {
|
||||
format!("Local variable `{name}` is annotated but never used")
|
||||
}
|
||||
CheckKind::UnusedImport(name, ignore_init) => {
|
||||
CheckKind::UnusedImport(name, ignore_init, ..) => {
|
||||
if *ignore_init {
|
||||
format!(
|
||||
"`{name}` imported but unused; consider adding to `__all__` or using a \
|
||||
@@ -2627,7 +2662,7 @@ impl CheckKind {
|
||||
format!("`{alias}` is deprecated, use `{target}`")
|
||||
}
|
||||
CheckKind::UselessObjectInheritance(name) => {
|
||||
format!("Class `{name}` inherits from object")
|
||||
format!("Class `{name}` inherits from `object`")
|
||||
}
|
||||
CheckKind::UsePEP585Annotation(name) => {
|
||||
format!(
|
||||
@@ -2653,14 +2688,24 @@ impl CheckKind {
|
||||
"Unnecessary parameters to `functools.lru_cache`".to_string()
|
||||
}
|
||||
CheckKind::UnnecessaryEncodeUTF8 => "Unnecessary call to `encode` as UTF-8".to_string(),
|
||||
CheckKind::RedundantOpenModes => "Unnecessary open mode parameters".to_string(),
|
||||
CheckKind::RedundantOpenModes(replacement) => match replacement {
|
||||
None => "Unnecessary open mode parameters".to_string(),
|
||||
Some(replacement) => {
|
||||
format!("Unnecessary open mode parameters, use \"{replacement}\"")
|
||||
}
|
||||
},
|
||||
CheckKind::RemoveSixCompat => "Unnecessary `six` compatibility usage".to_string(),
|
||||
CheckKind::DatetimeTimezoneUTC => "Use `datetime.UTC` alias".to_string(),
|
||||
CheckKind::NativeLiterals => "Unnecessary call to `str` and `bytes`".to_string(),
|
||||
CheckKind::NativeLiterals(literal_type) => {
|
||||
format!("Unnecessary call to `{literal_type}`")
|
||||
}
|
||||
CheckKind::OpenAlias => "Use builtin `open`".to_string(),
|
||||
CheckKind::ConvertTypedDictFunctionalToClass(name) => {
|
||||
format!("Convert `{name}` from `TypedDict` functional to class syntax")
|
||||
}
|
||||
CheckKind::ConvertNamedTupleFunctionalToClass(name) => {
|
||||
format!("Convert `{name}` from `NamedTuple` functional to class syntax")
|
||||
}
|
||||
CheckKind::ReplaceUniversalNewlines => {
|
||||
"`universal_newlines` is deprecated, use `text`".to_string()
|
||||
}
|
||||
@@ -2671,9 +2716,6 @@ impl CheckKind {
|
||||
"`cElementTree` is deprecated, use `ElementTree`".to_string()
|
||||
}
|
||||
CheckKind::RewriteUnicodeLiteral => "Remove unicode literals from strings".to_string(),
|
||||
CheckKind::ConvertNamedTupleFunctionalToClass(name) => {
|
||||
format!("Convert `{name}` from `NamedTuple` functional to class syntax")
|
||||
}
|
||||
// pydocstyle
|
||||
CheckKind::FitsOnOneLine => "One-line docstring should fit on one line".to_string(),
|
||||
CheckKind::BlankLineAfterSummary => {
|
||||
@@ -2850,14 +2892,13 @@ impl CheckKind {
|
||||
CheckKind::HardcodedBindAllInterfaces => {
|
||||
"Possible binding to all interfaces".to_string()
|
||||
}
|
||||
CheckKind::HardcodedPasswordString(string) => {
|
||||
format!("Possible hardcoded password: `\"{string}\"`")
|
||||
}
|
||||
CheckKind::HardcodedPasswordFuncArg(string) => {
|
||||
format!("Possible hardcoded password: `\"{string}\"`")
|
||||
}
|
||||
CheckKind::HardcodedPasswordDefault(string) => {
|
||||
format!("Possible hardcoded password: `\"{string}\"`")
|
||||
CheckKind::HardcodedPasswordString(string)
|
||||
| CheckKind::HardcodedPasswordFuncArg(string)
|
||||
| CheckKind::HardcodedPasswordDefault(string) => {
|
||||
format!(
|
||||
"Possible hardcoded password: `\"{}\"`",
|
||||
string.escape_debug()
|
||||
)
|
||||
}
|
||||
// flake8-blind-except
|
||||
CheckKind::BlindExcept(name) => format!("Do not catch blind exception: `{name}`"),
|
||||
@@ -3089,6 +3130,7 @@ impl CheckKind {
|
||||
self,
|
||||
CheckKind::AmbiguousUnicodeCharacterString(..)
|
||||
| CheckKind::AmbiguousUnicodeCharacterDocstring(..)
|
||||
| CheckKind::AmbiguousUnicodeCharacterComment(..)
|
||||
| CheckKind::BlankLineAfterLastSection(..)
|
||||
| CheckKind::BlankLineAfterSection(..)
|
||||
| CheckKind::BlankLineAfterSummary
|
||||
@@ -3101,7 +3143,7 @@ impl CheckKind {
|
||||
| CheckKind::DatetimeTimezoneUTC
|
||||
| CheckKind::DeprecatedUnittestAlias(..)
|
||||
| CheckKind::DoNotAssertFalse
|
||||
| CheckKind::DoNotAssignLambda
|
||||
| CheckKind::DoNotAssignLambda(..)
|
||||
| CheckKind::DuplicateHandlerException(..)
|
||||
| CheckKind::EndsInPeriod
|
||||
| CheckKind::EndsInPunctuation
|
||||
@@ -3109,11 +3151,11 @@ impl CheckKind {
|
||||
| CheckKind::ImplicitReturn
|
||||
| CheckKind::ImplicitReturnValue
|
||||
| CheckKind::InvalidEscapeSequence(..)
|
||||
| CheckKind::IsLiteral
|
||||
| CheckKind::IsLiteral(..)
|
||||
| CheckKind::KeyInDict(..)
|
||||
| CheckKind::MisplacedComparisonConstant(..)
|
||||
| CheckKind::MissingReturnTypeSpecialMethod(..)
|
||||
| CheckKind::NativeLiterals
|
||||
| CheckKind::NativeLiterals(..)
|
||||
| CheckKind::OpenAlias
|
||||
| CheckKind::NewLineAfterLastParagraph
|
||||
| CheckKind::ReplaceUniversalNewlines
|
||||
@@ -3136,10 +3178,10 @@ impl CheckKind {
|
||||
| CheckKind::OneBlankLineBeforeClass(..)
|
||||
| CheckKind::PEP3120UnnecessaryCodingComment
|
||||
| CheckKind::PPrintFound
|
||||
| CheckKind::PercentFormatExtraNamedArguments(..)
|
||||
| CheckKind::PrintFound
|
||||
| CheckKind::PercentFormatExtraNamedArguments(..)
|
||||
| CheckKind::RaiseNotImplemented
|
||||
| CheckKind::RedundantOpenModes
|
||||
| CheckKind::RedundantOpenModes(..)
|
||||
| CheckKind::RedundantTupleInExceptionHandler(..)
|
||||
| CheckKind::RemoveSixCompat
|
||||
| CheckKind::SectionNameEndsInColon(..)
|
||||
@@ -3171,7 +3213,7 @@ impl CheckKind {
|
||||
| CheckKind::UnnecessaryLiteralWithinTupleCall(..)
|
||||
| CheckKind::UnnecessaryReturnNone
|
||||
| CheckKind::UnsortedImports
|
||||
| CheckKind::UnusedImport(_, false)
|
||||
| CheckKind::UnusedImport(_, false, _)
|
||||
| CheckKind::UnusedLoopControlVariable(..)
|
||||
| CheckKind::UnusedNOQA(..)
|
||||
| CheckKind::UsePEP585Annotation(..)
|
||||
@@ -3182,6 +3224,235 @@ impl CheckKind {
|
||||
| CheckKind::UselessObjectInheritance(..)
|
||||
)
|
||||
}
|
||||
|
||||
/// The message used to describe the fix action for a given `CheckKind`.
|
||||
pub fn commit(&self) -> Option<String> {
|
||||
match self {
|
||||
CheckKind::AmbiguousUnicodeCharacterString(confusable, representant)
|
||||
| CheckKind::AmbiguousUnicodeCharacterDocstring(confusable, representant)
|
||||
| CheckKind::AmbiguousUnicodeCharacterComment(confusable, representant) => {
|
||||
Some(format!("Replace '{confusable}' with '{representant}'"))
|
||||
}
|
||||
CheckKind::BlankLineAfterLastSection(name) => {
|
||||
Some(format!("Add blank line after \"{name}\""))
|
||||
}
|
||||
CheckKind::BlankLineAfterSection(name) => {
|
||||
Some(format!("Add blank line after \"{name}\""))
|
||||
}
|
||||
CheckKind::BlankLineAfterSummary => Some("Insert single blank line".to_string()),
|
||||
CheckKind::BlankLineBeforeSection(name) => {
|
||||
Some(format!("Add blank line before \"{name}\""))
|
||||
}
|
||||
CheckKind::CapitalizeSectionName(name) => Some(format!("Capitalize \"{name}\"")),
|
||||
CheckKind::CommentedOutCode => Some("Remove commented-out code".to_string()),
|
||||
CheckKind::ConvertTypedDictFunctionalToClass(name)
|
||||
| CheckKind::ConvertNamedTupleFunctionalToClass(name) => {
|
||||
Some(format!("Convert `{name}` to class syntax"))
|
||||
}
|
||||
CheckKind::DashedUnderlineAfterSection(name) => {
|
||||
Some(format!("Add dashed line under \"{name}\""))
|
||||
}
|
||||
CheckKind::DatetimeTimezoneUTC => Some("Convert to `datetime.UTC` alias".to_string()),
|
||||
CheckKind::DeprecatedUnittestAlias(alias, target) => {
|
||||
Some(format!("Replace `{target}` with `{alias}`"))
|
||||
}
|
||||
CheckKind::DoNotAssertFalse => Some("Replace `assert False`".to_string()),
|
||||
CheckKind::DoNotAssignLambda(name) => Some(format!("Rewrite `{name}` as a `def`")),
|
||||
CheckKind::DuplicateHandlerException(..) => Some("De-duplicate exceptions".to_string()),
|
||||
CheckKind::EndsInPeriod => Some("Add period".to_string()),
|
||||
CheckKind::EndsInPunctuation => Some("Add closing punctuation".to_string()),
|
||||
CheckKind::GetAttrWithConstant => {
|
||||
Some("Replace `getattr` with attribute access".to_string())
|
||||
}
|
||||
CheckKind::ImplicitReturnValue => Some("Add explicit `None` return value".to_string()),
|
||||
CheckKind::ImplicitReturn => Some("Add explicit `return` statement".to_string()),
|
||||
CheckKind::InvalidEscapeSequence(..) => {
|
||||
Some("Add backslash to escape sequence".to_string())
|
||||
}
|
||||
CheckKind::IsLiteral(cmpop) => Some(match cmpop {
|
||||
IsCmpop::Is => "Replace `is` with `==`".to_string(),
|
||||
IsCmpop::IsNot => "Replace `is not` with `!=`".to_string(),
|
||||
}),
|
||||
CheckKind::KeyInDict(key, dict) => Some(format!("Convert to `{key} in {dict}`")),
|
||||
CheckKind::MisplacedComparisonConstant(comparison) => {
|
||||
Some(format!("Replace with {comparison}"))
|
||||
}
|
||||
CheckKind::MissingReturnTypeSpecialMethod(..) => {
|
||||
Some("Add `None` return type".to_string())
|
||||
}
|
||||
CheckKind::NativeLiterals(literal_type) => {
|
||||
Some(format!("Replace with `{literal_type}`"))
|
||||
}
|
||||
CheckKind::OpenAlias => Some("Replace with builtin `open`".to_string()),
|
||||
CheckKind::NewLineAfterLastParagraph => {
|
||||
Some("Move closing quotes to new line".to_string())
|
||||
}
|
||||
CheckKind::ReplaceUniversalNewlines => {
|
||||
Some("Replace with `text` keyword argument".to_string())
|
||||
}
|
||||
CheckKind::ReplaceStdoutStderr => {
|
||||
Some("Replace with `capture_output` keyword argument".to_string())
|
||||
}
|
||||
CheckKind::RewriteCElementTree => Some("Replace with `ElementTree`".to_string()),
|
||||
CheckKind::RewriteUnicodeLiteral => Some("Remove unicode prefix".to_string()),
|
||||
CheckKind::NewLineAfterSectionName(name) => {
|
||||
Some(format!("Add newline after \"{name}\""))
|
||||
}
|
||||
CheckKind::NoBlankLineBeforeFunction(..) => {
|
||||
Some("Remove blank line(s) before function docstring".to_string())
|
||||
}
|
||||
CheckKind::NoBlankLineAfterFunction(..) => {
|
||||
Some("Remove blank line(s) after function docstring".to_string())
|
||||
}
|
||||
CheckKind::NoBlankLineBeforeClass(..) => {
|
||||
Some("Remove blank line(s) before class docstring".to_string())
|
||||
}
|
||||
CheckKind::OneBlankLineBeforeClass(..) => {
|
||||
Some("Insert 1 blank line before class docstring".to_string())
|
||||
}
|
||||
CheckKind::OneBlankLineAfterClass(..) => {
|
||||
Some("Insert 1 blank line after class docstring".to_string())
|
||||
}
|
||||
CheckKind::NoBlankLinesBetweenHeaderAndContent(..) => {
|
||||
Some("Remove blank line(s)".to_string())
|
||||
}
|
||||
CheckKind::NoNewLineAtEndOfFile => Some("Add trailing newline".to_string()),
|
||||
CheckKind::NoOverIndentation => Some("Remove over-indentation".to_string()),
|
||||
CheckKind::NoSurroundingWhitespace => Some("Trim surrounding whitespace".to_string()),
|
||||
CheckKind::NoUnderIndentation => Some("Increase indentation".to_string()),
|
||||
CheckKind::NoneComparison(op) => Some(match op {
|
||||
EqCmpop::Eq => "Replace with `cond is None`".to_string(),
|
||||
EqCmpop::NotEq => "Replace with `cond is not None`".to_string(),
|
||||
}),
|
||||
CheckKind::NotInTest => Some("Convert to `not in`".to_string()),
|
||||
CheckKind::NotIsTest => Some("Convert to `is not`".to_string()),
|
||||
CheckKind::PEP3120UnnecessaryCodingComment => {
|
||||
Some("Remove unnecessary coding comment".to_string())
|
||||
}
|
||||
CheckKind::PPrintFound => Some("Remove `pprint`".to_string()),
|
||||
CheckKind::PercentFormatExtraNamedArguments(missing)
|
||||
| CheckKind::StringDotFormatExtraNamedArguments(missing) => {
|
||||
let message = missing.join(", ");
|
||||
Some(format!("Remove extra named arguments: {message}"))
|
||||
}
|
||||
CheckKind::PrintFound => Some("Remove `print`".to_string()),
|
||||
CheckKind::RaiseNotImplemented => Some("Use `raise NotImplementedError`".to_string()),
|
||||
CheckKind::RedundantOpenModes(replacement) => Some(match replacement {
|
||||
None => "Remove open mode parameters".to_string(),
|
||||
Some(replacement) => {
|
||||
format!("Replace with \"{replacement}\"")
|
||||
}
|
||||
}),
|
||||
CheckKind::RedundantTupleInExceptionHandler(name) => {
|
||||
Some(format!("Replace with `except {name}`"))
|
||||
}
|
||||
CheckKind::RemoveSixCompat => Some("Remove `six` usage".to_string()),
|
||||
CheckKind::SectionNameEndsInColon(name) => Some(format!("Add colon to \"{name}\"")),
|
||||
CheckKind::SectionNotOverIndented(name) => {
|
||||
Some(format!("Remove over-indentation from \"{name}\""))
|
||||
}
|
||||
CheckKind::SectionUnderlineAfterName(name) => {
|
||||
Some(format!("Add underline to \"{name}\""))
|
||||
}
|
||||
CheckKind::SectionUnderlineMatchesSectionLength(name) => {
|
||||
Some(format!("Adjust underline length to match \"{name}\""))
|
||||
}
|
||||
CheckKind::SectionUnderlineNotOverIndented(name) => {
|
||||
Some(format!("Remove over-indentation from \"{name}\" underline"))
|
||||
}
|
||||
CheckKind::SetAttrWithConstant => Some("Replace `setattr` with assignment".to_string()),
|
||||
CheckKind::SuperCallWithParameters => Some("Remove `__super__` parameters".to_string()),
|
||||
CheckKind::TrueFalseComparison(true, EqCmpop::Eq) => {
|
||||
Some("Replace with `cond is True`".to_string())
|
||||
}
|
||||
CheckKind::TrueFalseComparison(true, EqCmpop::NotEq) => {
|
||||
Some("Replace with `cond is not True`".to_string())
|
||||
}
|
||||
CheckKind::TrueFalseComparison(false, EqCmpop::Eq) => {
|
||||
Some("Replace with `cond is False`".to_string())
|
||||
}
|
||||
CheckKind::TrueFalseComparison(false, EqCmpop::NotEq) => {
|
||||
Some("Replace with `cond is not False`".to_string())
|
||||
}
|
||||
CheckKind::TypeOfPrimitive(primitive) => Some(format!(
|
||||
"Replace `type(...)` with `{}`",
|
||||
primitive.builtin()
|
||||
)),
|
||||
CheckKind::TypingTextStrAlias => Some("Replace with `str`".to_string()),
|
||||
CheckKind::UnnecessaryCallAroundSorted(func) => {
|
||||
Some(format!("Remove unnecessary `{func}` call"))
|
||||
}
|
||||
CheckKind::UnnecessaryCollectionCall(..) => Some("Rewrite as a literal".to_string()),
|
||||
CheckKind::UnnecessaryComprehension(obj_type) => {
|
||||
Some(format!("Rewrite using `{obj_type}()`"))
|
||||
}
|
||||
CheckKind::UnnecessaryEncodeUTF8 => Some("Remove unnecessary `encode`".to_string()),
|
||||
CheckKind::UnnecessaryFutureImport(..) => {
|
||||
Some("Remove unnecessary `__future__` import".to_string())
|
||||
}
|
||||
CheckKind::UnnecessaryGeneratorDict => {
|
||||
Some("Rewrite as a `dict` comprehension".to_string())
|
||||
}
|
||||
CheckKind::UnnecessaryGeneratorList => {
|
||||
Some("Rewrite as a `list` comprehension".to_string())
|
||||
}
|
||||
CheckKind::UnnecessaryGeneratorSet => {
|
||||
Some("Rewrite as a `set` comprehension".to_string())
|
||||
}
|
||||
CheckKind::UnnecessaryLRUCacheParams => {
|
||||
Some("Remove unnecessary parameters".to_string())
|
||||
}
|
||||
CheckKind::UnnecessaryListCall => Some("Remove outer `list` call".to_string()),
|
||||
CheckKind::UnnecessaryListComprehensionDict => {
|
||||
Some("Rewrite as a `dict` comprehension".to_string())
|
||||
}
|
||||
CheckKind::UnnecessaryListComprehensionSet => {
|
||||
Some("Rewrite as a `set` comprehension".to_string())
|
||||
}
|
||||
CheckKind::UnnecessaryLiteralDict(..) => {
|
||||
Some("Rewrite as a `dict` literal".to_string())
|
||||
}
|
||||
CheckKind::UnnecessaryLiteralSet(..) => Some("Rewrite as a `set` literal".to_string()),
|
||||
CheckKind::UnnecessaryLiteralWithinTupleCall(literal) => Some({
|
||||
if literal == "list" {
|
||||
"Rewrite as a `tuple` literal".to_string()
|
||||
} else {
|
||||
"Remove outer `tuple` call".to_string()
|
||||
}
|
||||
}),
|
||||
CheckKind::UnnecessaryLiteralWithinListCall(literal) => Some({
|
||||
if literal == "list" {
|
||||
"Remove outer `list` call".to_string()
|
||||
} else {
|
||||
"Rewrite as a `list` literal".to_string()
|
||||
}
|
||||
}),
|
||||
CheckKind::UnnecessaryReturnNone => Some("Remove explicit `return None`".to_string()),
|
||||
CheckKind::UnsortedImports => Some("Organize imports".to_string()),
|
||||
CheckKind::UnusedImport(name, false, multiple) => {
|
||||
if *multiple {
|
||||
Some("Remove unused import".to_string())
|
||||
} else {
|
||||
Some(format!("Remove unused import: `{name}`"))
|
||||
}
|
||||
}
|
||||
CheckKind::UnusedLoopControlVariable(name) => {
|
||||
Some(format!("Rename unused `{name}` to `_{name}`"))
|
||||
}
|
||||
CheckKind::UnusedNOQA(..) => Some("Remove unused `noqa` directive".to_string()),
|
||||
CheckKind::UsePEP585Annotation(name) => {
|
||||
Some(format!("Replace `{name}` with `{}`", name.to_lowercase(),))
|
||||
}
|
||||
CheckKind::UsePEP604Annotation => Some("Convert to `X | Y`".to_string()),
|
||||
CheckKind::UseSysExit(name) => Some(format!("Replace `{name}` with `sys.exit()`")),
|
||||
CheckKind::UselessImportAlias => Some("Remove import alias".to_string()),
|
||||
CheckKind::UselessMetaclassType => Some("Remove `__metaclass__ = type`".to_string()),
|
||||
CheckKind::UselessObjectInheritance(..) => {
|
||||
Some("Remove `object` inheritance".to_string())
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||
@@ -3362,4 +3633,17 @@ mod tests {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn fixable_codes() {
|
||||
for check_code in CheckCode::iter() {
|
||||
let kind = check_code.kind();
|
||||
if kind.fixable() {
|
||||
assert!(
|
||||
kind.commit().is_some(),
|
||||
"{check_code:?} is fixable but has no commit message."
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -283,8 +283,6 @@ pub enum CheckCodePrefix {
|
||||
F821,
|
||||
F822,
|
||||
F823,
|
||||
F83,
|
||||
F831,
|
||||
F84,
|
||||
F841,
|
||||
F842,
|
||||
@@ -647,7 +645,6 @@ impl CheckCodePrefix {
|
||||
CheckCode::F821,
|
||||
CheckCode::F822,
|
||||
CheckCode::F823,
|
||||
CheckCode::F831,
|
||||
CheckCode::F841,
|
||||
CheckCode::F842,
|
||||
CheckCode::F901,
|
||||
@@ -1506,7 +1503,6 @@ impl CheckCodePrefix {
|
||||
CheckCode::F821,
|
||||
CheckCode::F822,
|
||||
CheckCode::F823,
|
||||
CheckCode::F831,
|
||||
CheckCode::F841,
|
||||
CheckCode::F842,
|
||||
CheckCode::F901,
|
||||
@@ -1640,7 +1636,6 @@ impl CheckCodePrefix {
|
||||
CheckCode::F821,
|
||||
CheckCode::F822,
|
||||
CheckCode::F823,
|
||||
CheckCode::F831,
|
||||
CheckCode::F841,
|
||||
CheckCode::F842,
|
||||
],
|
||||
@@ -1650,8 +1645,6 @@ impl CheckCodePrefix {
|
||||
CheckCodePrefix::F821 => vec![CheckCode::F821],
|
||||
CheckCodePrefix::F822 => vec![CheckCode::F822],
|
||||
CheckCodePrefix::F823 => vec![CheckCode::F823],
|
||||
CheckCodePrefix::F83 => vec![CheckCode::F831],
|
||||
CheckCodePrefix::F831 => vec![CheckCode::F831],
|
||||
CheckCodePrefix::F84 => vec![CheckCode::F841, CheckCode::F842],
|
||||
CheckCodePrefix::F841 => vec![CheckCode::F841],
|
||||
CheckCodePrefix::F842 => vec![CheckCode::F842],
|
||||
@@ -3102,8 +3095,6 @@ impl CheckCodePrefix {
|
||||
CheckCodePrefix::F821 => SuffixLength::Three,
|
||||
CheckCodePrefix::F822 => SuffixLength::Three,
|
||||
CheckCodePrefix::F823 => SuffixLength::Three,
|
||||
CheckCodePrefix::F83 => SuffixLength::Two,
|
||||
CheckCodePrefix::F831 => SuffixLength::Three,
|
||||
CheckCodePrefix::F84 => SuffixLength::Two,
|
||||
CheckCodePrefix::F841 => SuffixLength::Three,
|
||||
CheckCodePrefix::F842 => SuffixLength::Three,
|
||||
|
||||
@@ -26,7 +26,7 @@ use crate::message::Message;
|
||||
use crate::resolver::{FileDiscovery, PyprojectDiscovery};
|
||||
use crate::settings::flags;
|
||||
use crate::settings::types::SerializationFormat;
|
||||
use crate::{cache, fs, packages, resolver};
|
||||
use crate::{cache, fs, one_time_warning, packages, resolver};
|
||||
|
||||
/// Run the linter over a collection of files.
|
||||
pub fn run(
|
||||
@@ -44,6 +44,15 @@ pub fn run(
|
||||
let duration = start.elapsed();
|
||||
debug!("Identified files to lint in: {:?}", duration);
|
||||
|
||||
if paths.is_empty() {
|
||||
one_time_warning!(
|
||||
"{} {}",
|
||||
"warning:".yellow().bold(),
|
||||
"No Python files found under the given path(s)"
|
||||
);
|
||||
return Ok(Diagnostics::default());
|
||||
}
|
||||
|
||||
// Validate the `Settings` and return any errors.
|
||||
resolver.validate(pyproject_strategy)?;
|
||||
|
||||
@@ -185,6 +194,15 @@ pub fn add_noqa(
|
||||
let duration = start.elapsed();
|
||||
debug!("Identified files to lint in: {:?}", duration);
|
||||
|
||||
if paths.is_empty() {
|
||||
one_time_warning!(
|
||||
"{} {}",
|
||||
"warning:".yellow().bold(),
|
||||
"No Python files found under the given path(s)"
|
||||
);
|
||||
return Ok(0);
|
||||
}
|
||||
|
||||
// Validate the `Settings` and return any errors.
|
||||
resolver.validate(pyproject_strategy)?;
|
||||
|
||||
@@ -250,6 +268,15 @@ pub fn show_files(
|
||||
let (paths, resolver) =
|
||||
resolver::python_files_in_path(files, pyproject_strategy, file_strategy, overrides)?;
|
||||
|
||||
if paths.is_empty() {
|
||||
one_time_warning!(
|
||||
"{} {}",
|
||||
"warning:".yellow().bold(),
|
||||
"No Python files found under the given path(s)"
|
||||
);
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
// Validate the `Settings` and return any errors.
|
||||
resolver.validate(pyproject_strategy)?;
|
||||
|
||||
|
||||
@@ -16,13 +16,12 @@ mod tests {
|
||||
#[test_case(CheckCode::ERA001, Path::new("ERA001.py"); "ERA001")]
|
||||
fn checks(check_code: CheckCode, path: &Path) -> Result<()> {
|
||||
let snapshot = format!("{}_{}", check_code.as_ref(), path.to_string_lossy());
|
||||
let mut checks = test_path(
|
||||
let checks = test_path(
|
||||
Path::new("./resources/test/fixtures/eradicate")
|
||||
.join(path)
|
||||
.as_path(),
|
||||
&settings::Settings::for_rule(check_code),
|
||||
)?;
|
||||
checks.sort_by_key(|check| check.location);
|
||||
insta::assert_yaml_snapshot!(snapshot, checks);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -24,13 +24,12 @@ mod tests {
|
||||
#[test_case(CheckCode::YTT303, Path::new("YTT303.py"); "YTT303")]
|
||||
fn checks(check_code: CheckCode, path: &Path) -> Result<()> {
|
||||
let snapshot = format!("{}_{}", check_code.as_ref(), path.to_string_lossy());
|
||||
let mut checks = test_path(
|
||||
let checks = test_path(
|
||||
Path::new("./resources/test/fixtures/flake8_2020")
|
||||
.join(path)
|
||||
.as_path(),
|
||||
&settings::Settings::for_rule(check_code),
|
||||
)?;
|
||||
checks.sort_by_key(|check| check.location);
|
||||
insta::assert_yaml_snapshot!(snapshot, checks);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn defaults() -> Result<()> {
|
||||
let mut checks = test_path(
|
||||
let checks = test_path(
|
||||
Path::new("./resources/test/fixtures/flake8_annotations/annotation_presence.py"),
|
||||
&Settings {
|
||||
..Settings::for_rules(vec![
|
||||
@@ -33,14 +33,13 @@ mod tests {
|
||||
])
|
||||
},
|
||||
)?;
|
||||
checks.sort_by_key(|check| check.location);
|
||||
insta::assert_yaml_snapshot!(checks);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn suppress_dummy_args() -> Result<()> {
|
||||
let mut checks = test_path(
|
||||
let checks = test_path(
|
||||
Path::new("./resources/test/fixtures/flake8_annotations/suppress_dummy_args.py"),
|
||||
&Settings {
|
||||
flake8_annotations: flake8_annotations::settings::Settings {
|
||||
@@ -58,14 +57,13 @@ mod tests {
|
||||
])
|
||||
},
|
||||
)?;
|
||||
checks.sort_by_key(|check| check.location);
|
||||
insta::assert_yaml_snapshot!(checks);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn mypy_init_return() -> Result<()> {
|
||||
let mut checks = test_path(
|
||||
let checks = test_path(
|
||||
Path::new("./resources/test/fixtures/flake8_annotations/mypy_init_return.py"),
|
||||
&Settings {
|
||||
flake8_annotations: flake8_annotations::settings::Settings {
|
||||
@@ -83,14 +81,13 @@ mod tests {
|
||||
])
|
||||
},
|
||||
)?;
|
||||
checks.sort_by_key(|check| check.location);
|
||||
insta::assert_yaml_snapshot!(checks);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn suppress_none_returning() -> Result<()> {
|
||||
let mut checks = test_path(
|
||||
let checks = test_path(
|
||||
Path::new("./resources/test/fixtures/flake8_annotations/suppress_none_returning.py"),
|
||||
&Settings {
|
||||
flake8_annotations: flake8_annotations::settings::Settings {
|
||||
@@ -108,14 +105,13 @@ mod tests {
|
||||
])
|
||||
},
|
||||
)?;
|
||||
checks.sort_by_key(|check| check.location);
|
||||
insta::assert_yaml_snapshot!(checks);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn allow_star_arg_any() -> Result<()> {
|
||||
let mut checks = test_path(
|
||||
let checks = test_path(
|
||||
Path::new("./resources/test/fixtures/flake8_annotations/allow_star_arg_any.py"),
|
||||
&Settings {
|
||||
flake8_annotations: flake8_annotations::settings::Settings {
|
||||
@@ -127,14 +123,13 @@ mod tests {
|
||||
..Settings::for_rules(vec![CheckCode::ANN401])
|
||||
},
|
||||
)?;
|
||||
checks.sort_by_key(|check| check.location);
|
||||
insta::assert_yaml_snapshot!(checks);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn allow_overload() -> Result<()> {
|
||||
let mut checks = test_path(
|
||||
let checks = test_path(
|
||||
Path::new("./resources/test/fixtures/flake8_annotations/allow_overload.py"),
|
||||
&Settings {
|
||||
..Settings::for_rules(vec![
|
||||
@@ -146,7 +141,6 @@ mod tests {
|
||||
])
|
||||
},
|
||||
)?;
|
||||
checks.sort_by_key(|check| check.location);
|
||||
insta::assert_yaml_snapshot!(checks);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -21,13 +21,12 @@ mod tests {
|
||||
#[test_case(CheckCode::S107, Path::new("S107.py"); "S107")]
|
||||
fn checks(check_code: CheckCode, path: &Path) -> Result<()> {
|
||||
let snapshot = format!("{}_{}", check_code.as_ref(), path.to_string_lossy());
|
||||
let mut checks = test_path(
|
||||
let checks = test_path(
|
||||
Path::new("./resources/test/fixtures/flake8_bandit")
|
||||
.join(path)
|
||||
.as_path(),
|
||||
&settings::Settings::for_rule(check_code),
|
||||
)?;
|
||||
checks.sort_by_key(|check| check.location);
|
||||
insta::assert_yaml_snapshot!(snapshot, checks);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -342,4 +342,34 @@ expression: checks
|
||||
column: 28
|
||||
fix: ~
|
||||
parent: ~
|
||||
- kind:
|
||||
HardcodedPasswordString: "1\n2"
|
||||
location:
|
||||
row: 55
|
||||
column: 12
|
||||
end_location:
|
||||
row: 55
|
||||
column: 18
|
||||
fix: ~
|
||||
parent: ~
|
||||
- kind:
|
||||
HardcodedPasswordString: "3\t4"
|
||||
location:
|
||||
row: 58
|
||||
column: 12
|
||||
end_location:
|
||||
row: 58
|
||||
column: 18
|
||||
fix: ~
|
||||
parent: ~
|
||||
- kind:
|
||||
HardcodedPasswordString: "5\r6"
|
||||
location:
|
||||
row: 61
|
||||
column: 12
|
||||
end_location:
|
||||
row: 61
|
||||
column: 18
|
||||
fix: ~
|
||||
parent: ~
|
||||
|
||||
|
||||
@@ -15,13 +15,12 @@ mod tests {
|
||||
#[test_case(CheckCode::BLE001, Path::new("BLE.py"); "BLE001")]
|
||||
fn checks(check_code: CheckCode, path: &Path) -> Result<()> {
|
||||
let snapshot = format!("{}_{}", check_code.as_ref(), path.to_string_lossy());
|
||||
let mut checks = test_path(
|
||||
let checks = test_path(
|
||||
Path::new("./resources/test/fixtures/flake8_blind_except")
|
||||
.join(path)
|
||||
.as_path(),
|
||||
&settings::Settings::for_rule(check_code),
|
||||
)?;
|
||||
checks.sort_by_key(|check| check.location);
|
||||
insta::assert_yaml_snapshot!(snapshot, checks);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -17,13 +17,12 @@ mod tests {
|
||||
#[test_case(CheckCode::FBT003, Path::new("FBT.py"); "FBT003")]
|
||||
fn checks(check_code: CheckCode, path: &Path) -> Result<()> {
|
||||
let snapshot = format!("{}_{}", check_code.as_ref(), path.to_string_lossy());
|
||||
let mut checks = test_path(
|
||||
let checks = test_path(
|
||||
Path::new("./resources/test/fixtures/flake8_boolean_trap")
|
||||
.join(path)
|
||||
.as_path(),
|
||||
&settings::Settings::for_rule(check_code),
|
||||
)?;
|
||||
checks.sort_by_key(|check| check.location);
|
||||
insta::assert_yaml_snapshot!(snapshot, checks);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -42,13 +42,12 @@ mod tests {
|
||||
#[test_case(CheckCode::B905, Path::new("B905.py"); "B905")]
|
||||
fn checks(check_code: CheckCode, path: &Path) -> Result<()> {
|
||||
let snapshot = format!("{}_{}", check_code.as_ref(), path.to_string_lossy());
|
||||
let mut checks = test_path(
|
||||
let checks = test_path(
|
||||
Path::new("./resources/test/fixtures/flake8_bugbear")
|
||||
.join(path)
|
||||
.as_path(),
|
||||
&Settings::for_rule(check_code),
|
||||
)?;
|
||||
checks.sort_by_key(|check| check.location);
|
||||
insta::assert_yaml_snapshot!(snapshot, checks);
|
||||
Ok(())
|
||||
}
|
||||
@@ -56,7 +55,7 @@ mod tests {
|
||||
#[test]
|
||||
fn extend_immutable_calls() -> Result<()> {
|
||||
let snapshot = "extend_immutable_calls".to_string();
|
||||
let mut checks = test_path(
|
||||
let checks = test_path(
|
||||
Path::new("./resources/test/fixtures/flake8_bugbear/B008_extended.py"),
|
||||
&Settings {
|
||||
flake8_bugbear: flake8_bugbear::settings::Settings {
|
||||
@@ -68,7 +67,6 @@ mod tests {
|
||||
..Settings::for_rules(vec![CheckCode::B008])
|
||||
},
|
||||
)?;
|
||||
checks.sort_by_key(|check| check.location);
|
||||
insta::assert_yaml_snapshot!(snapshot, checks);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -47,8 +47,11 @@ pub fn assert_false(checker: &mut Checker, stmt: &Stmt, test: &Expr, msg: Option
|
||||
|
||||
let mut check = Check::new(CheckKind::DoNotAssertFalse, Range::from_located(test));
|
||||
if checker.patch(check.kind.code()) {
|
||||
let mut generator =
|
||||
SourceCodeGenerator::new(checker.style.indentation(), checker.style.quote());
|
||||
let mut generator = SourceCodeGenerator::new(
|
||||
checker.style.indentation(),
|
||||
checker.style.quote(),
|
||||
checker.style.line_ending(),
|
||||
);
|
||||
generator.unparse_stmt(&assertion_error(msg));
|
||||
if let Ok(content) = generator.generate() {
|
||||
check.amend(Fix::replacement(
|
||||
|
||||
@@ -54,8 +54,11 @@ fn duplicate_handler_exceptions<'a>(
|
||||
Range::from_located(expr),
|
||||
);
|
||||
if checker.patch(check.kind.code()) {
|
||||
let mut generator =
|
||||
SourceCodeGenerator::new(checker.style.indentation(), checker.style.quote());
|
||||
let mut generator = SourceCodeGenerator::new(
|
||||
checker.style.indentation(),
|
||||
checker.style.quote(),
|
||||
checker.style.line_ending(),
|
||||
);
|
||||
if unique_elts.len() == 1 {
|
||||
generator.unparse_expr(unique_elts[0], 0);
|
||||
} else {
|
||||
|
||||
@@ -12,8 +12,6 @@ use crate::checks::{Check, CheckKind};
|
||||
struct LoadedNamesVisitor<'a> {
|
||||
// Tuple of: name, defining expression, and defining range.
|
||||
names: Vec<(&'a str, &'a Expr, Range)>,
|
||||
// If we're in an f-string, the range of the defining expression.
|
||||
in_f_string: Option<Range>,
|
||||
}
|
||||
|
||||
/// `Visitor` to collect all used identifiers in a statement.
|
||||
@@ -24,18 +22,10 @@ where
|
||||
fn visit_expr(&mut self, expr: &'b Expr) {
|
||||
match &expr.node {
|
||||
ExprKind::JoinedStr { .. } => {
|
||||
let prev_in_f_string = self.in_f_string;
|
||||
self.in_f_string = Some(Range::from_located(expr));
|
||||
visitor::walk_expr(self, expr);
|
||||
self.in_f_string = prev_in_f_string;
|
||||
}
|
||||
ExprKind::Name { id, ctx } if matches!(ctx, ExprContext::Load) => {
|
||||
self.names.push((
|
||||
id,
|
||||
expr,
|
||||
self.in_f_string
|
||||
.unwrap_or_else(|| Range::from_located(expr)),
|
||||
));
|
||||
self.names.push((id, expr, Range::from_located(expr)));
|
||||
}
|
||||
_ => visitor::walk_expr(self, expr),
|
||||
}
|
||||
|
||||
@@ -46,8 +46,11 @@ pub fn getattr_with_constant(checker: &mut Checker, expr: &Expr, func: &Expr, ar
|
||||
|
||||
let mut check = Check::new(CheckKind::GetAttrWithConstant, Range::from_located(expr));
|
||||
if checker.patch(check.kind.code()) {
|
||||
let mut generator =
|
||||
SourceCodeGenerator::new(checker.style.indentation(), checker.style.quote());
|
||||
let mut generator = SourceCodeGenerator::new(
|
||||
checker.style.indentation(),
|
||||
checker.style.quote(),
|
||||
checker.style.line_ending(),
|
||||
);
|
||||
generator.unparse_expr(&attribute(obj, value), 0);
|
||||
if let Ok(content) = generator.generate() {
|
||||
check.amend(Fix::replacement(
|
||||
|
||||
@@ -23,8 +23,11 @@ pub fn redundant_tuple_in_exception_handler(checker: &mut Checker, handlers: &[E
|
||||
Range::from_located(type_),
|
||||
);
|
||||
if checker.patch(check.kind.code()) {
|
||||
let mut generator =
|
||||
SourceCodeGenerator::new(checker.style.indentation(), checker.style.quote());
|
||||
let mut generator = SourceCodeGenerator::new(
|
||||
checker.style.indentation(),
|
||||
checker.style.quote(),
|
||||
checker.style.line_ending(),
|
||||
);
|
||||
generator.unparse_expr(elt, 0);
|
||||
if let Ok(content) = generator.generate() {
|
||||
check.amend(Fix::replacement(
|
||||
|
||||
@@ -34,7 +34,11 @@ fn assignment(
|
||||
type_comment: None,
|
||||
},
|
||||
);
|
||||
let mut generator = SourceCodeGenerator::new(stylist.indentation(), stylist.quote());
|
||||
let mut generator = SourceCodeGenerator::new(
|
||||
stylist.indentation(),
|
||||
stylist.quote(),
|
||||
stylist.line_ending(),
|
||||
);
|
||||
generator.unparse_stmt(&stmt);
|
||||
generator.generate().map_err(std::convert::Into::into)
|
||||
}
|
||||
|
||||
@@ -166,10 +166,10 @@ expression: checks
|
||||
FunctionUsesLoopVariable: i
|
||||
location:
|
||||
row: 82
|
||||
column: 12
|
||||
column: 15
|
||||
end_location:
|
||||
row: 82
|
||||
column: 18
|
||||
column: 16
|
||||
fix: ~
|
||||
parent: ~
|
||||
|
||||
|
||||
@@ -18,13 +18,12 @@ mod tests {
|
||||
#[test_case(CheckCode::A003, Path::new("A003.py"); "A003")]
|
||||
fn checks(check_code: CheckCode, path: &Path) -> Result<()> {
|
||||
let snapshot = format!("{}_{}", check_code.as_ref(), path.to_string_lossy());
|
||||
let mut checks = test_path(
|
||||
let checks = test_path(
|
||||
Path::new("./resources/test/fixtures/flake8_builtins")
|
||||
.join(path)
|
||||
.as_path(),
|
||||
&settings::Settings::for_rule(check_code),
|
||||
)?;
|
||||
checks.sort_by_key(|check| check.location);
|
||||
insta::assert_yaml_snapshot!(snapshot, checks);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -32,13 +32,12 @@ mod tests {
|
||||
|
||||
fn checks(check_code: CheckCode, path: &Path) -> Result<()> {
|
||||
let snapshot = format!("{}_{}", check_code.as_ref(), path.to_string_lossy());
|
||||
let mut checks = test_path(
|
||||
let checks = test_path(
|
||||
Path::new("./resources/test/fixtures/flake8_comprehensions")
|
||||
.join(path)
|
||||
.as_path(),
|
||||
&settings::Settings::for_rule(check_code),
|
||||
)?;
|
||||
checks.sort_by_key(|check| check.location);
|
||||
insta::assert_yaml_snapshot!(snapshot, checks);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -23,13 +23,12 @@ mod tests {
|
||||
#[test_case(CheckCode::DTZ012, Path::new("DTZ012.py"); "DTZ012")]
|
||||
fn checks(check_code: CheckCode, path: &Path) -> Result<()> {
|
||||
let snapshot = format!("{}_{}", check_code.as_ref(), path.to_string_lossy());
|
||||
let mut checks = test_path(
|
||||
let checks = test_path(
|
||||
Path::new("./resources/test/fixtures/flake8_datetimez")
|
||||
.join(path)
|
||||
.as_path(),
|
||||
&settings::Settings::for_rule(check_code),
|
||||
)?;
|
||||
checks.sort_by_key(|check| check.location);
|
||||
insta::assert_yaml_snapshot!(snapshot, checks);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -16,13 +16,12 @@ mod tests {
|
||||
#[test_case(CheckCode::T100, Path::new("T100.py"); "T100")]
|
||||
fn checks(check_code: CheckCode, path: &Path) -> Result<()> {
|
||||
let snapshot = format!("{}_{}", check_code.as_ref(), path.to_string_lossy());
|
||||
let mut checks = test_path(
|
||||
let checks = test_path(
|
||||
Path::new("./resources/test/fixtures/flake8_debugger")
|
||||
.join(path)
|
||||
.as_path(),
|
||||
&settings::Settings::for_rule(check_code),
|
||||
)?;
|
||||
checks.sort_by_key(|check| check.location);
|
||||
insta::assert_yaml_snapshot!(snapshot, checks);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn defaults() -> Result<()> {
|
||||
let mut checks = test_path(
|
||||
let checks = test_path(
|
||||
Path::new("./resources/test/fixtures/flake8_errmsg/EM.py"),
|
||||
&settings::Settings::for_rules(vec![
|
||||
CheckCode::EM101,
|
||||
@@ -21,14 +21,13 @@ mod tests {
|
||||
CheckCode::EM103,
|
||||
]),
|
||||
)?;
|
||||
checks.sort_by_key(|check| check.location);
|
||||
insta::assert_yaml_snapshot!("defaults", checks);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn custom() -> Result<()> {
|
||||
let mut checks = test_path(
|
||||
let checks = test_path(
|
||||
Path::new("./resources/test/fixtures/flake8_errmsg/EM.py"),
|
||||
&settings::Settings {
|
||||
flake8_errmsg: flake8_errmsg::settings::Settings {
|
||||
@@ -41,7 +40,6 @@ mod tests {
|
||||
])
|
||||
},
|
||||
)?;
|
||||
checks.sort_by_key(|check| check.location);
|
||||
insta::assert_yaml_snapshot!("custom", checks);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -17,13 +17,12 @@ mod tests {
|
||||
#[test_case(CheckCode::ISC003, Path::new("ISC.py"); "ISC003")]
|
||||
fn checks(check_code: CheckCode, path: &Path) -> Result<()> {
|
||||
let snapshot = format!("{}_{}", check_code.as_ref(), path.to_string_lossy());
|
||||
let mut checks = test_path(
|
||||
let checks = test_path(
|
||||
Path::new("./resources/test/fixtures/flake8_implicit_str_concat")
|
||||
.join(path)
|
||||
.as_path(),
|
||||
&settings::Settings::for_rule(check_code),
|
||||
)?;
|
||||
checks.sort_by_key(|check| check.location);
|
||||
insta::assert_yaml_snapshot!(snapshot, checks);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -15,18 +15,17 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn defaults() -> Result<()> {
|
||||
let mut checks = test_path(
|
||||
let checks = test_path(
|
||||
Path::new("./resources/test/fixtures/flake8_import_conventions/defaults.py"),
|
||||
&Settings::for_rule(CheckCode::ICN001),
|
||||
)?;
|
||||
checks.sort_by_key(|check| check.location);
|
||||
insta::assert_yaml_snapshot!("defaults", checks);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn custom() -> Result<()> {
|
||||
let mut checks = test_path(
|
||||
let checks = test_path(
|
||||
Path::new("./resources/test/fixtures/flake8_import_conventions/custom.py"),
|
||||
&Settings {
|
||||
flake8_import_conventions: flake8_import_conventions::settings::Options {
|
||||
@@ -40,14 +39,13 @@ mod tests {
|
||||
..Settings::for_rule(CheckCode::ICN001)
|
||||
},
|
||||
)?;
|
||||
checks.sort_by_key(|check| check.location);
|
||||
insta::assert_yaml_snapshot!("custom", checks);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn remove_defaults() -> Result<()> {
|
||||
let mut checks = test_path(
|
||||
let checks = test_path(
|
||||
Path::new("./resources/test/fixtures/flake8_import_conventions/remove_default.py"),
|
||||
&Settings {
|
||||
flake8_import_conventions: flake8_import_conventions::settings::Options {
|
||||
@@ -63,14 +61,13 @@ mod tests {
|
||||
..Settings::for_rule(CheckCode::ICN001)
|
||||
},
|
||||
)?;
|
||||
checks.sort_by_key(|check| check.location);
|
||||
insta::assert_yaml_snapshot!("remove_default", checks);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn override_defaults() -> Result<()> {
|
||||
let mut checks = test_path(
|
||||
let checks = test_path(
|
||||
Path::new("./resources/test/fixtures/flake8_import_conventions/override_default.py"),
|
||||
&Settings {
|
||||
flake8_import_conventions: flake8_import_conventions::settings::Options {
|
||||
@@ -84,7 +81,6 @@ mod tests {
|
||||
..Settings::for_rule(CheckCode::ICN001)
|
||||
},
|
||||
)?;
|
||||
checks.sort_by_key(|check| check.location);
|
||||
insta::assert_yaml_snapshot!("override_default", checks);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -16,13 +16,12 @@ mod tests {
|
||||
#[test_case(CheckCode::T203, Path::new("T203.py"); "T203")]
|
||||
fn checks(check_code: CheckCode, path: &Path) -> Result<()> {
|
||||
let snapshot = format!("{}_{}", check_code.as_ref(), path.to_string_lossy());
|
||||
let mut checks = test_path(
|
||||
let checks = test_path(
|
||||
Path::new("./resources/test/fixtures/flake8_print")
|
||||
.join(path)
|
||||
.as_path(),
|
||||
&settings::Settings::for_rule(check_code),
|
||||
)?;
|
||||
checks.sort_by_key(|check| check.location);
|
||||
insta::assert_yaml_snapshot!(snapshot, checks);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ use crate::checkers::ast::Checker;
|
||||
use crate::checks::{Check, CheckKind};
|
||||
|
||||
/// T201, T203
|
||||
pub fn print_call(checker: &mut Checker, expr: &Expr, func: &Expr, keywords: &[Keyword]) {
|
||||
pub fn print_call(checker: &mut Checker, func: &Expr, keywords: &[Keyword]) {
|
||||
let mut check = {
|
||||
let call_path = dealias_call_path(collect_call_paths(func), &checker.import_aliases);
|
||||
if match_call_path(&call_path, "", "print", &checker.from_imports) {
|
||||
@@ -27,9 +27,9 @@ pub fn print_call(checker: &mut Checker, expr: &Expr, func: &Expr, keywords: &[K
|
||||
}
|
||||
}
|
||||
}
|
||||
Check::new(CheckKind::PrintFound, Range::from_located(expr))
|
||||
Check::new(CheckKind::PrintFound, Range::from_located(func))
|
||||
} else if match_call_path(&call_path, "pprint", "pprint", &checker.from_imports) {
|
||||
Check::new(CheckKind::PPrintFound, Range::from_located(expr))
|
||||
Check::new(CheckKind::PPrintFound, Range::from_located(func))
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ expression: checks
|
||||
column: 0
|
||||
end_location:
|
||||
row: 4
|
||||
column: 22
|
||||
column: 5
|
||||
fix:
|
||||
content: ""
|
||||
location:
|
||||
@@ -24,7 +24,7 @@ expression: checks
|
||||
column: 0
|
||||
end_location:
|
||||
row: 5
|
||||
column: 33
|
||||
column: 5
|
||||
fix:
|
||||
content: ""
|
||||
location:
|
||||
@@ -40,7 +40,7 @@ expression: checks
|
||||
column: 0
|
||||
end_location:
|
||||
row: 6
|
||||
column: 39
|
||||
column: 5
|
||||
fix:
|
||||
content: ""
|
||||
location:
|
||||
@@ -56,7 +56,7 @@ expression: checks
|
||||
column: 0
|
||||
end_location:
|
||||
row: 7
|
||||
column: 39
|
||||
column: 5
|
||||
fix:
|
||||
content: ""
|
||||
location:
|
||||
|
||||
@@ -8,7 +8,7 @@ expression: checks
|
||||
column: 0
|
||||
end_location:
|
||||
row: 3
|
||||
column: 23
|
||||
column: 6
|
||||
fix:
|
||||
content: ""
|
||||
location:
|
||||
@@ -24,7 +24,7 @@ expression: checks
|
||||
column: 0
|
||||
end_location:
|
||||
row: 7
|
||||
column: 30
|
||||
column: 13
|
||||
fix:
|
||||
content: ""
|
||||
location:
|
||||
|
||||
@@ -20,7 +20,7 @@ mod tests {
|
||||
#[test_case(Path::new("doubles_wrapped.py"))]
|
||||
fn doubles(path: &Path) -> Result<()> {
|
||||
let snapshot = format!("doubles_{}", path.to_string_lossy());
|
||||
let mut checks = test_path(
|
||||
let checks = test_path(
|
||||
Path::new("./resources/test/fixtures/flake8_quotes")
|
||||
.join(path)
|
||||
.as_path(),
|
||||
@@ -39,7 +39,6 @@ mod tests {
|
||||
])
|
||||
},
|
||||
)?;
|
||||
checks.sort_by_key(|check| check.location);
|
||||
insta::assert_yaml_snapshot!(snapshot, checks);
|
||||
Ok(())
|
||||
}
|
||||
@@ -51,7 +50,7 @@ mod tests {
|
||||
#[test_case(Path::new("singles_wrapped.py"))]
|
||||
fn singles(path: &Path) -> Result<()> {
|
||||
let snapshot = format!("singles_{}", path.to_string_lossy());
|
||||
let mut checks = test_path(
|
||||
let checks = test_path(
|
||||
Path::new("./resources/test/fixtures/flake8_quotes")
|
||||
.join(path)
|
||||
.as_path(),
|
||||
@@ -70,7 +69,6 @@ mod tests {
|
||||
])
|
||||
},
|
||||
)?;
|
||||
checks.sort_by_key(|check| check.location);
|
||||
insta::assert_yaml_snapshot!(snapshot, checks);
|
||||
Ok(())
|
||||
}
|
||||
@@ -87,7 +85,7 @@ mod tests {
|
||||
#[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 = test_path(
|
||||
let checks = test_path(
|
||||
Path::new("./resources/test/fixtures/flake8_quotes")
|
||||
.join(path)
|
||||
.as_path(),
|
||||
@@ -106,7 +104,6 @@ mod tests {
|
||||
])
|
||||
},
|
||||
)?;
|
||||
checks.sort_by_key(|check| check.location);
|
||||
insta::assert_yaml_snapshot!(snapshot, checks);
|
||||
Ok(())
|
||||
}
|
||||
@@ -123,7 +120,7 @@ mod tests {
|
||||
#[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 = test_path(
|
||||
let checks = test_path(
|
||||
Path::new("./resources/test/fixtures/flake8_quotes")
|
||||
.join(path)
|
||||
.as_path(),
|
||||
@@ -142,7 +139,6 @@ mod tests {
|
||||
])
|
||||
},
|
||||
)?;
|
||||
checks.sort_by_key(|check| check.location);
|
||||
insta::assert_yaml_snapshot!(snapshot, checks);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -1,50 +0,0 @@
|
||||
---
|
||||
source: src/flake8_quotes/checks.rs
|
||||
expression: checks
|
||||
---
|
||||
- kind:
|
||||
BadQuotesMultilineString: single
|
||||
location:
|
||||
row: 5
|
||||
column: 0
|
||||
end_location:
|
||||
row: 7
|
||||
column: 3
|
||||
fix: ~
|
||||
- kind:
|
||||
BadQuotesMultilineString: single
|
||||
location:
|
||||
row: 16
|
||||
column: 4
|
||||
end_location:
|
||||
row: 18
|
||||
column: 7
|
||||
fix: ~
|
||||
- kind:
|
||||
BadQuotesMultilineString: single
|
||||
location:
|
||||
row: 21
|
||||
column: 20
|
||||
end_location:
|
||||
row: 22
|
||||
column: 37
|
||||
fix: ~
|
||||
- kind:
|
||||
BadQuotesMultilineString: single
|
||||
location:
|
||||
row: 30
|
||||
column: 8
|
||||
end_location:
|
||||
row: 32
|
||||
column: 11
|
||||
fix: ~
|
||||
- kind:
|
||||
BadQuotesMultilineString: single
|
||||
location:
|
||||
row: 35
|
||||
column: 12
|
||||
end_location:
|
||||
row: 37
|
||||
column: 15
|
||||
fix: ~
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
---
|
||||
source: src/flake8_quotes/checks.rs
|
||||
expression: checks
|
||||
---
|
||||
- kind:
|
||||
BadQuotesMultilineString: single
|
||||
location:
|
||||
row: 3
|
||||
column: 4
|
||||
end_location:
|
||||
row: 3
|
||||
column: 27
|
||||
fix: ~
|
||||
- kind:
|
||||
BadQuotesMultilineString: single
|
||||
location:
|
||||
row: 5
|
||||
column: 22
|
||||
end_location:
|
||||
row: 5
|
||||
column: 43
|
||||
fix: ~
|
||||
|
||||
@@ -1,50 +0,0 @@
|
||||
---
|
||||
source: src/flake8_quotes/checks.rs
|
||||
expression: checks
|
||||
---
|
||||
- kind:
|
||||
BadQuotesMultilineString: single
|
||||
location:
|
||||
row: 3
|
||||
column: 4
|
||||
end_location:
|
||||
row: 3
|
||||
column: 26
|
||||
fix: ~
|
||||
- kind:
|
||||
BadQuotesMultilineString: single
|
||||
location:
|
||||
row: 11
|
||||
column: 4
|
||||
end_location:
|
||||
row: 11
|
||||
column: 26
|
||||
fix: ~
|
||||
- kind:
|
||||
BadQuotesMultilineString: single
|
||||
location:
|
||||
row: 15
|
||||
column: 38
|
||||
end_location:
|
||||
row: 17
|
||||
column: 3
|
||||
fix: ~
|
||||
- kind:
|
||||
BadQuotesMultilineString: single
|
||||
location:
|
||||
row: 17
|
||||
column: 4
|
||||
end_location:
|
||||
row: 17
|
||||
column: 19
|
||||
fix: ~
|
||||
- kind:
|
||||
BadQuotesMultilineString: single
|
||||
location:
|
||||
row: 21
|
||||
column: 4
|
||||
end_location:
|
||||
row: 21
|
||||
column: 27
|
||||
fix: ~
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
---
|
||||
source: src/flake8_quotes/checks.rs
|
||||
expression: checks
|
||||
---
|
||||
- kind:
|
||||
BadQuotesMultilineString: single
|
||||
location:
|
||||
row: 4
|
||||
column: 0
|
||||
end_location:
|
||||
row: 6
|
||||
column: 3
|
||||
fix: ~
|
||||
- kind:
|
||||
BadQuotesMultilineString: single
|
||||
location:
|
||||
row: 9
|
||||
column: 0
|
||||
end_location:
|
||||
row: 11
|
||||
column: 3
|
||||
fix: ~
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
---
|
||||
source: src/flake8_quotes/checks.rs
|
||||
expression: checks
|
||||
---
|
||||
- kind:
|
||||
BadQuotesMultilineString: single
|
||||
location:
|
||||
row: 2
|
||||
column: 0
|
||||
end_location:
|
||||
row: 2
|
||||
column: 31
|
||||
fix: ~
|
||||
- kind:
|
||||
BadQuotesMultilineString: single
|
||||
location:
|
||||
row: 6
|
||||
column: 0
|
||||
end_location:
|
||||
row: 6
|
||||
column: 31
|
||||
fix: ~
|
||||
|
||||
@@ -1,32 +0,0 @@
|
||||
---
|
||||
source: src/flake8_quotes/checks.rs
|
||||
expression: checks
|
||||
---
|
||||
- kind:
|
||||
BadQuotesDocstring: double
|
||||
location:
|
||||
row: 1
|
||||
column: 0
|
||||
end_location:
|
||||
row: 3
|
||||
column: 3
|
||||
fix: ~
|
||||
- kind:
|
||||
BadQuotesDocstring: double
|
||||
location:
|
||||
row: 14
|
||||
column: 4
|
||||
end_location:
|
||||
row: 16
|
||||
column: 7
|
||||
fix: ~
|
||||
- kind:
|
||||
BadQuotesDocstring: double
|
||||
location:
|
||||
row: 26
|
||||
column: 8
|
||||
end_location:
|
||||
row: 28
|
||||
column: 11
|
||||
fix: ~
|
||||
|
||||
@@ -1,32 +0,0 @@
|
||||
---
|
||||
source: src/flake8_quotes/checks.rs
|
||||
expression: checks
|
||||
---
|
||||
- kind:
|
||||
BadQuotesDocstring: double
|
||||
location:
|
||||
row: 2
|
||||
column: 4
|
||||
end_location:
|
||||
row: 2
|
||||
column: 53
|
||||
fix: ~
|
||||
- kind:
|
||||
BadQuotesDocstring: double
|
||||
location:
|
||||
row: 6
|
||||
column: 8
|
||||
end_location:
|
||||
row: 6
|
||||
column: 57
|
||||
fix: ~
|
||||
- kind:
|
||||
BadQuotesDocstring: double
|
||||
location:
|
||||
row: 9
|
||||
column: 28
|
||||
end_location:
|
||||
row: 9
|
||||
column: 52
|
||||
fix: ~
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
---
|
||||
source: src/flake8_quotes/checks.rs
|
||||
expression: checks
|
||||
---
|
||||
- kind:
|
||||
BadQuotesDocstring: double
|
||||
location:
|
||||
row: 2
|
||||
column: 4
|
||||
end_location:
|
||||
row: 2
|
||||
column: 56
|
||||
fix: ~
|
||||
- kind:
|
||||
BadQuotesDocstring: double
|
||||
location:
|
||||
row: 8
|
||||
column: 4
|
||||
end_location:
|
||||
row: 10
|
||||
column: 7
|
||||
fix: ~
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
---
|
||||
source: src/flake8_quotes/checks.rs
|
||||
expression: checks
|
||||
---
|
||||
- kind:
|
||||
BadQuotesDocstring: double
|
||||
location:
|
||||
row: 1
|
||||
column: 0
|
||||
end_location:
|
||||
row: 3
|
||||
column: 3
|
||||
fix: ~
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
---
|
||||
source: src/flake8_quotes/checks.rs
|
||||
expression: checks
|
||||
---
|
||||
- kind:
|
||||
BadQuotesDocstring: double
|
||||
location:
|
||||
row: 1
|
||||
column: 0
|
||||
end_location:
|
||||
row: 1
|
||||
column: 49
|
||||
fix: ~
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
---
|
||||
source: src/flake8_quotes/checks.rs
|
||||
expression: checks
|
||||
---
|
||||
- kind:
|
||||
BadQuotesInlineString: single
|
||||
location:
|
||||
row: 1
|
||||
column: 24
|
||||
end_location:
|
||||
row: 1
|
||||
column: 45
|
||||
fix: ~
|
||||
- kind:
|
||||
BadQuotesInlineString: single
|
||||
location:
|
||||
row: 2
|
||||
column: 24
|
||||
end_location:
|
||||
row: 2
|
||||
column: 46
|
||||
fix: ~
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
---
|
||||
source: src/flake8_quotes/checks.rs
|
||||
expression: checks
|
||||
---
|
||||
- kind: AvoidQuoteEscape
|
||||
location:
|
||||
row: 1
|
||||
column: 25
|
||||
end_location:
|
||||
row: 1
|
||||
column: 47
|
||||
fix: ~
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
---
|
||||
source: src/flake8_quotes/checks.rs
|
||||
expression: checks
|
||||
---
|
||||
- kind:
|
||||
BadQuotesMultilineString: single
|
||||
location:
|
||||
row: 1
|
||||
column: 4
|
||||
end_location:
|
||||
row: 3
|
||||
column: 12
|
||||
fix: ~
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
---
|
||||
source: src/flake8_quotes/checks.rs
|
||||
expression: checks
|
||||
---
|
||||
[]
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
---
|
||||
source: src/flake8_quotes/checks.rs
|
||||
expression: checks
|
||||
---
|
||||
[]
|
||||
|
||||
@@ -1,32 +0,0 @@
|
||||
---
|
||||
source: src/flake8_quotes/checks.rs
|
||||
expression: checks
|
||||
---
|
||||
- kind:
|
||||
BadQuotesDocstring: single
|
||||
location:
|
||||
row: 1
|
||||
column: 0
|
||||
end_location:
|
||||
row: 3
|
||||
column: 3
|
||||
fix: ~
|
||||
- kind:
|
||||
BadQuotesDocstring: single
|
||||
location:
|
||||
row: 12
|
||||
column: 4
|
||||
end_location:
|
||||
row: 14
|
||||
column: 7
|
||||
fix: ~
|
||||
- kind:
|
||||
BadQuotesDocstring: single
|
||||
location:
|
||||
row: 24
|
||||
column: 8
|
||||
end_location:
|
||||
row: 26
|
||||
column: 11
|
||||
fix: ~
|
||||
|
||||
@@ -1,32 +0,0 @@
|
||||
---
|
||||
source: src/flake8_quotes/checks.rs
|
||||
expression: checks
|
||||
---
|
||||
- kind:
|
||||
BadQuotesDocstring: single
|
||||
location:
|
||||
row: 2
|
||||
column: 4
|
||||
end_location:
|
||||
row: 2
|
||||
column: 53
|
||||
fix: ~
|
||||
- kind:
|
||||
BadQuotesDocstring: single
|
||||
location:
|
||||
row: 6
|
||||
column: 8
|
||||
end_location:
|
||||
row: 6
|
||||
column: 57
|
||||
fix: ~
|
||||
- kind:
|
||||
BadQuotesDocstring: single
|
||||
location:
|
||||
row: 9
|
||||
column: 28
|
||||
end_location:
|
||||
row: 9
|
||||
column: 52
|
||||
fix: ~
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
---
|
||||
source: src/flake8_quotes/checks.rs
|
||||
expression: checks
|
||||
---
|
||||
- kind:
|
||||
BadQuotesDocstring: single
|
||||
location:
|
||||
row: 2
|
||||
column: 4
|
||||
end_location:
|
||||
row: 2
|
||||
column: 56
|
||||
fix: ~
|
||||
- kind:
|
||||
BadQuotesDocstring: single
|
||||
location:
|
||||
row: 8
|
||||
column: 4
|
||||
end_location:
|
||||
row: 10
|
||||
column: 7
|
||||
fix: ~
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
---
|
||||
source: src/flake8_quotes/checks.rs
|
||||
expression: checks
|
||||
---
|
||||
- kind:
|
||||
BadQuotesDocstring: single
|
||||
location:
|
||||
row: 1
|
||||
column: 0
|
||||
end_location:
|
||||
row: 3
|
||||
column: 3
|
||||
fix: ~
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
---
|
||||
source: src/flake8_quotes/checks.rs
|
||||
expression: checks
|
||||
---
|
||||
- kind:
|
||||
BadQuotesDocstring: single
|
||||
location:
|
||||
row: 1
|
||||
column: 0
|
||||
end_location:
|
||||
row: 1
|
||||
column: 49
|
||||
fix: ~
|
||||
|
||||
@@ -1,59 +0,0 @@
|
||||
---
|
||||
source: src/flake8_quotes/checks.rs
|
||||
expression: checks
|
||||
---
|
||||
- kind:
|
||||
BadQuotesMultilineString: double
|
||||
location:
|
||||
row: 5
|
||||
column: 0
|
||||
end_location:
|
||||
row: 7
|
||||
column: 3
|
||||
fix: ~
|
||||
- kind:
|
||||
BadQuotesMultilineString: double
|
||||
location:
|
||||
row: 11
|
||||
column: 20
|
||||
end_location:
|
||||
row: 13
|
||||
column: 3
|
||||
fix: ~
|
||||
- kind:
|
||||
BadQuotesMultilineString: double
|
||||
location:
|
||||
row: 18
|
||||
column: 4
|
||||
end_location:
|
||||
row: 20
|
||||
column: 7
|
||||
fix: ~
|
||||
- kind:
|
||||
BadQuotesMultilineString: double
|
||||
location:
|
||||
row: 23
|
||||
column: 20
|
||||
end_location:
|
||||
row: 24
|
||||
column: 37
|
||||
fix: ~
|
||||
- kind:
|
||||
BadQuotesMultilineString: double
|
||||
location:
|
||||
row: 32
|
||||
column: 8
|
||||
end_location:
|
||||
row: 34
|
||||
column: 11
|
||||
fix: ~
|
||||
- kind:
|
||||
BadQuotesMultilineString: double
|
||||
location:
|
||||
row: 37
|
||||
column: 12
|
||||
end_location:
|
||||
row: 39
|
||||
column: 15
|
||||
fix: ~
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
---
|
||||
source: src/flake8_quotes/checks.rs
|
||||
expression: checks
|
||||
---
|
||||
- kind:
|
||||
BadQuotesMultilineString: double
|
||||
location:
|
||||
row: 3
|
||||
column: 4
|
||||
end_location:
|
||||
row: 3
|
||||
column: 27
|
||||
fix: ~
|
||||
- kind:
|
||||
BadQuotesMultilineString: double
|
||||
location:
|
||||
row: 5
|
||||
column: 22
|
||||
end_location:
|
||||
row: 5
|
||||
column: 43
|
||||
fix: ~
|
||||
|
||||
@@ -1,50 +0,0 @@
|
||||
---
|
||||
source: src/flake8_quotes/checks.rs
|
||||
expression: checks
|
||||
---
|
||||
- kind:
|
||||
BadQuotesMultilineString: double
|
||||
location:
|
||||
row: 3
|
||||
column: 4
|
||||
end_location:
|
||||
row: 3
|
||||
column: 26
|
||||
fix: ~
|
||||
- kind:
|
||||
BadQuotesMultilineString: double
|
||||
location:
|
||||
row: 11
|
||||
column: 4
|
||||
end_location:
|
||||
row: 11
|
||||
column: 26
|
||||
fix: ~
|
||||
- kind:
|
||||
BadQuotesMultilineString: double
|
||||
location:
|
||||
row: 15
|
||||
column: 38
|
||||
end_location:
|
||||
row: 17
|
||||
column: 3
|
||||
fix: ~
|
||||
- kind:
|
||||
BadQuotesMultilineString: double
|
||||
location:
|
||||
row: 17
|
||||
column: 4
|
||||
end_location:
|
||||
row: 17
|
||||
column: 19
|
||||
fix: ~
|
||||
- kind:
|
||||
BadQuotesMultilineString: double
|
||||
location:
|
||||
row: 21
|
||||
column: 4
|
||||
end_location:
|
||||
row: 21
|
||||
column: 27
|
||||
fix: ~
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
---
|
||||
source: src/flake8_quotes/checks.rs
|
||||
expression: checks
|
||||
---
|
||||
- kind:
|
||||
BadQuotesMultilineString: double
|
||||
location:
|
||||
row: 4
|
||||
column: 0
|
||||
end_location:
|
||||
row: 6
|
||||
column: 3
|
||||
fix: ~
|
||||
- kind:
|
||||
BadQuotesMultilineString: double
|
||||
location:
|
||||
row: 9
|
||||
column: 0
|
||||
end_location:
|
||||
row: 11
|
||||
column: 3
|
||||
fix: ~
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
---
|
||||
source: src/flake8_quotes/checks.rs
|
||||
expression: checks
|
||||
---
|
||||
- kind:
|
||||
BadQuotesMultilineString: double
|
||||
location:
|
||||
row: 2
|
||||
column: 0
|
||||
end_location:
|
||||
row: 2
|
||||
column: 31
|
||||
fix: ~
|
||||
- kind:
|
||||
BadQuotesMultilineString: double
|
||||
location:
|
||||
row: 6
|
||||
column: 0
|
||||
end_location:
|
||||
row: 6
|
||||
column: 31
|
||||
fix: ~
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
---
|
||||
source: src/flake8_quotes/checks.rs
|
||||
expression: checks
|
||||
---
|
||||
- kind:
|
||||
BadQuotesInlineString: double
|
||||
location:
|
||||
row: 1
|
||||
column: 24
|
||||
end_location:
|
||||
row: 1
|
||||
column: 45
|
||||
fix: ~
|
||||
- kind:
|
||||
BadQuotesInlineString: double
|
||||
location:
|
||||
row: 2
|
||||
column: 24
|
||||
end_location:
|
||||
row: 2
|
||||
column: 46
|
||||
fix: ~
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
---
|
||||
source: src/flake8_quotes/checks.rs
|
||||
expression: checks
|
||||
---
|
||||
- kind: AvoidQuoteEscape
|
||||
location:
|
||||
row: 1
|
||||
column: 25
|
||||
end_location:
|
||||
row: 1
|
||||
column: 47
|
||||
fix: ~
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
---
|
||||
source: src/flake8_quotes/checks.rs
|
||||
expression: checks
|
||||
---
|
||||
- kind:
|
||||
BadQuotesMultilineString: double
|
||||
location:
|
||||
row: 1
|
||||
column: 4
|
||||
end_location:
|
||||
row: 3
|
||||
column: 12
|
||||
fix: ~
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
---
|
||||
source: src/flake8_quotes/checks.rs
|
||||
expression: checks
|
||||
---
|
||||
[]
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
---
|
||||
source: src/flake8_quotes/checks.rs
|
||||
expression: checks
|
||||
---
|
||||
[]
|
||||
|
||||
@@ -23,13 +23,12 @@ mod tests {
|
||||
#[test_case(CheckCode::RET508, Path::new("RET508.py"); "RET508")]
|
||||
fn checks(check_code: CheckCode, path: &Path) -> Result<()> {
|
||||
let snapshot = format!("{}_{}", check_code.as_ref(), path.to_string_lossy());
|
||||
let mut checks = test_path(
|
||||
let checks = test_path(
|
||||
Path::new("./resources/test/fixtures/flake8_return")
|
||||
.join(path)
|
||||
.as_path(),
|
||||
&Settings::for_rule(check_code),
|
||||
)?;
|
||||
checks.sort_by_key(|check| check.location);
|
||||
insta::assert_yaml_snapshot!(snapshot, checks);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -19,8 +19,6 @@ 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> {
|
||||
@@ -37,7 +35,7 @@ impl<'a> ReturnVisitor<'a> {
|
||||
.assigns
|
||||
.entry(id)
|
||||
.or_insert_with(Vec::new)
|
||||
.push(self.in_f_string.unwrap_or(expr.location));
|
||||
.push(expr.location);
|
||||
return;
|
||||
}
|
||||
_ => {}
|
||||
@@ -78,7 +76,7 @@ impl<'a> Visitor<'a> for ReturnVisitor<'a> {
|
||||
.refs
|
||||
.entry(id)
|
||||
.or_insert_with(Vec::new)
|
||||
.push(self.in_f_string.unwrap_or(value.location));
|
||||
.push(value.location);
|
||||
}
|
||||
|
||||
visitor::walk_expr(self, value);
|
||||
@@ -123,7 +121,7 @@ impl<'a> Visitor<'a> for ReturnVisitor<'a> {
|
||||
.refs
|
||||
.entry(name)
|
||||
.or_insert_with(Vec::new)
|
||||
.push(self.in_f_string.unwrap_or(expr.location));
|
||||
.push(expr.location);
|
||||
}
|
||||
}
|
||||
ExprKind::Name { id, .. } => {
|
||||
@@ -131,13 +129,10 @@ impl<'a> Visitor<'a> for ReturnVisitor<'a> {
|
||||
.refs
|
||||
.entry(id)
|
||||
.or_insert_with(Vec::new)
|
||||
.push(self.in_f_string.unwrap_or(expr.location));
|
||||
.push(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),
|
||||
}
|
||||
|
||||
@@ -15,13 +15,12 @@ mod tests {
|
||||
#[test_case(CheckCode::SIM118, Path::new("SIM118.py"); "SIM118")]
|
||||
fn checks(check_code: CheckCode, path: &Path) -> Result<()> {
|
||||
let snapshot = format!("{}_{}", check_code.as_ref(), path.to_string_lossy());
|
||||
let mut checks = test_path(
|
||||
let checks = test_path(
|
||||
Path::new("./resources/test/fixtures/flake8_simplify")
|
||||
.join(path)
|
||||
.as_path(),
|
||||
&settings::Settings::for_rule(check_code),
|
||||
)?;
|
||||
checks.sort_by_key(|check| check.location);
|
||||
insta::assert_yaml_snapshot!(snapshot, checks);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn ban_parent_imports() -> Result<()> {
|
||||
let mut checks = test_path(
|
||||
let checks = test_path(
|
||||
Path::new("./resources/test/fixtures/flake8_tidy_imports/TID252.py"),
|
||||
&Settings {
|
||||
flake8_tidy_imports: flake8_tidy_imports::settings::Settings {
|
||||
@@ -25,14 +25,13 @@ mod tests {
|
||||
..Settings::for_rules(vec![CheckCode::TID252])
|
||||
},
|
||||
)?;
|
||||
checks.sort_by_key(|check| check.location);
|
||||
insta::assert_yaml_snapshot!(checks);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ban_all_imports() -> Result<()> {
|
||||
let mut checks = test_path(
|
||||
let checks = test_path(
|
||||
Path::new("./resources/test/fixtures/flake8_tidy_imports/TID252.py"),
|
||||
&Settings {
|
||||
flake8_tidy_imports: flake8_tidy_imports::settings::Settings {
|
||||
@@ -42,14 +41,13 @@ mod tests {
|
||||
..Settings::for_rules(vec![CheckCode::TID252])
|
||||
},
|
||||
)?;
|
||||
checks.sort_by_key(|check| check.location);
|
||||
insta::assert_yaml_snapshot!(checks);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn banned_api_true_positives() -> Result<()> {
|
||||
let mut checks = test_path(
|
||||
let checks = test_path(
|
||||
Path::new("./resources/test/fixtures/flake8_tidy_imports/TID251.py"),
|
||||
&Settings {
|
||||
flake8_tidy_imports: flake8_tidy_imports::settings::Settings {
|
||||
@@ -72,14 +70,13 @@ mod tests {
|
||||
..Settings::for_rules(vec![CheckCode::TID251])
|
||||
},
|
||||
)?;
|
||||
checks.sort_by_key(|check| check.location);
|
||||
insta::assert_yaml_snapshot!(checks);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn banned_api_false_positives() -> Result<()> {
|
||||
let mut checks = test_path(
|
||||
let checks = test_path(
|
||||
Path::new("./resources/test/fixtures/flake8_tidy_imports/TID251_false_positives.py"),
|
||||
&Settings {
|
||||
flake8_tidy_imports: flake8_tidy_imports::settings::Settings {
|
||||
@@ -94,7 +91,6 @@ mod tests {
|
||||
..Settings::for_rules(vec![CheckCode::TID251])
|
||||
},
|
||||
)?;
|
||||
checks.sort_by_key(|check| check.location);
|
||||
insta::assert_yaml_snapshot!(checks);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -22,20 +22,19 @@ mod tests {
|
||||
#[test_case(CheckCode::ARG005, Path::new("ARG.py"); "ARG005")]
|
||||
fn checks(check_code: CheckCode, path: &Path) -> Result<()> {
|
||||
let snapshot = format!("{}_{}", check_code.as_ref(), path.to_string_lossy());
|
||||
let mut checks = test_path(
|
||||
let checks = test_path(
|
||||
Path::new("./resources/test/fixtures/flake8_unused_arguments")
|
||||
.join(path)
|
||||
.as_path(),
|
||||
&settings::Settings::for_rule(check_code),
|
||||
)?;
|
||||
checks.sort_by_key(|check| check.location);
|
||||
insta::assert_yaml_snapshot!(snapshot, checks);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ignore_variadic_names() -> Result<()> {
|
||||
let mut checks = test_path(
|
||||
let checks = test_path(
|
||||
Path::new("./resources/test/fixtures/flake8_unused_arguments/ignore_variadic_names.py"),
|
||||
&settings::Settings {
|
||||
flake8_unused_arguments: flake8_unused_arguments::settings::Settings {
|
||||
@@ -50,14 +49,13 @@ mod tests {
|
||||
])
|
||||
},
|
||||
)?;
|
||||
checks.sort_by_key(|check| check.location);
|
||||
insta::assert_yaml_snapshot!(checks);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn enforce_variadic_names() -> Result<()> {
|
||||
let mut checks = test_path(
|
||||
let checks = test_path(
|
||||
Path::new("./resources/test/fixtures/flake8_unused_arguments/ignore_variadic_names.py"),
|
||||
&settings::Settings {
|
||||
flake8_unused_arguments: flake8_unused_arguments::settings::Settings {
|
||||
@@ -72,7 +70,6 @@ mod tests {
|
||||
])
|
||||
},
|
||||
)?;
|
||||
checks.sort_by_key(|check| check.location);
|
||||
insta::assert_yaml_snapshot!(checks);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -685,7 +685,7 @@ mod tests {
|
||||
#[test_case(Path::new("line_ending_cr.py"))]
|
||||
fn default(path: &Path) -> Result<()> {
|
||||
let snapshot = format!("{}", path.to_string_lossy());
|
||||
let mut checks = test_path(
|
||||
let checks = test_path(
|
||||
Path::new("./resources/test/fixtures/isort")
|
||||
.join(path)
|
||||
.as_path(),
|
||||
@@ -694,7 +694,6 @@ mod tests {
|
||||
..Settings::for_rule(CheckCode::I001)
|
||||
},
|
||||
)?;
|
||||
checks.sort_by_key(|check| check.location);
|
||||
insta::assert_yaml_snapshot!(snapshot, checks);
|
||||
Ok(())
|
||||
}
|
||||
@@ -702,7 +701,7 @@ mod tests {
|
||||
#[test_case(Path::new("combine_as_imports.py"))]
|
||||
fn combine_as_imports(path: &Path) -> Result<()> {
|
||||
let snapshot = format!("combine_as_imports_{}", path.to_string_lossy());
|
||||
let mut checks = test_path(
|
||||
let checks = test_path(
|
||||
Path::new("./resources/test/fixtures/isort")
|
||||
.join(path)
|
||||
.as_path(),
|
||||
@@ -715,7 +714,6 @@ mod tests {
|
||||
..Settings::for_rule(CheckCode::I001)
|
||||
},
|
||||
)?;
|
||||
checks.sort_by_key(|check| check.location);
|
||||
insta::assert_yaml_snapshot!(snapshot, checks);
|
||||
Ok(())
|
||||
}
|
||||
@@ -723,7 +721,7 @@ mod tests {
|
||||
#[test_case(Path::new("force_wrap_aliases.py"))]
|
||||
fn force_wrap_aliases(path: &Path) -> Result<()> {
|
||||
let snapshot = format!("force_wrap_aliases_{}", path.to_string_lossy());
|
||||
let mut checks = test_path(
|
||||
let checks = test_path(
|
||||
Path::new("./resources/test/fixtures/isort")
|
||||
.join(path)
|
||||
.as_path(),
|
||||
@@ -737,7 +735,6 @@ mod tests {
|
||||
..Settings::for_rule(CheckCode::I001)
|
||||
},
|
||||
)?;
|
||||
checks.sort_by_key(|check| check.location);
|
||||
insta::assert_yaml_snapshot!(snapshot, checks);
|
||||
Ok(())
|
||||
}
|
||||
@@ -745,7 +742,7 @@ mod tests {
|
||||
#[test_case(Path::new("magic_trailing_comma.py"))]
|
||||
fn no_split_on_trailing_comma(path: &Path) -> Result<()> {
|
||||
let snapshot = format!("split_on_trailing_comma_{}", path.to_string_lossy());
|
||||
let mut checks = test_path(
|
||||
let checks = test_path(
|
||||
Path::new("./resources/test/fixtures/isort")
|
||||
.join(path)
|
||||
.as_path(),
|
||||
@@ -758,7 +755,6 @@ mod tests {
|
||||
..Settings::for_rule(CheckCode::I001)
|
||||
},
|
||||
)?;
|
||||
checks.sort_by_key(|check| check.location);
|
||||
insta::assert_yaml_snapshot!(snapshot, checks);
|
||||
Ok(())
|
||||
}
|
||||
@@ -766,7 +762,7 @@ mod tests {
|
||||
#[test_case(Path::new("force_single_line.py"))]
|
||||
fn force_single_line(path: &Path) -> Result<()> {
|
||||
let snapshot = format!("force_single_line_{}", path.to_string_lossy());
|
||||
let mut checks = test_path(
|
||||
let checks = test_path(
|
||||
Path::new("./resources/test/fixtures/isort")
|
||||
.join(path)
|
||||
.as_path(),
|
||||
@@ -782,7 +778,6 @@ mod tests {
|
||||
..Settings::for_rule(CheckCode::I001)
|
||||
},
|
||||
)?;
|
||||
checks.sort_by_key(|check| check.location);
|
||||
insta::assert_yaml_snapshot!(snapshot, checks);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -95,7 +95,7 @@ pub fn check_imports(
|
||||
end_location: Location::new(range.end_location.row() + 1 + num_trailing_lines, 0),
|
||||
};
|
||||
let actual = dedent(&locator.slice_source_code_range(&range));
|
||||
if actual == expected {
|
||||
if actual == dedent(&expected) {
|
||||
None
|
||||
} else {
|
||||
let mut check = Check::new(CheckKind::UnsortedImports, range);
|
||||
|
||||
@@ -2,10 +2,9 @@ use std::path::Path;
|
||||
|
||||
use rustpython_ast::Location;
|
||||
use rustpython_parser::lexer::LexResult;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde::Serialize;
|
||||
use wasm_bindgen::prelude::*;
|
||||
|
||||
use crate::autofix::Fix;
|
||||
use crate::checks::CheckCode;
|
||||
use crate::checks_gen::CheckCodePrefix;
|
||||
use crate::linter::check_path;
|
||||
@@ -39,6 +38,7 @@ export interface Check {
|
||||
};
|
||||
fix: {
|
||||
content: string;
|
||||
message: string | null;
|
||||
location: {
|
||||
row: number;
|
||||
column: number;
|
||||
@@ -51,13 +51,21 @@ export interface Check {
|
||||
};
|
||||
"#;
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||
struct Message {
|
||||
#[derive(Serialize)]
|
||||
struct ExpandedMessage {
|
||||
code: CheckCode,
|
||||
message: String,
|
||||
location: Location,
|
||||
end_location: Location,
|
||||
fix: Option<Fix>,
|
||||
fix: Option<ExpandedFix>,
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
struct ExpandedFix {
|
||||
content: String,
|
||||
message: Option<String>,
|
||||
location: Location,
|
||||
end_location: Location,
|
||||
}
|
||||
|
||||
#[wasm_bindgen(start)]
|
||||
@@ -161,14 +169,19 @@ pub fn check(contents: &str, options: JsValue) -> Result<JsValue, JsValue> {
|
||||
)
|
||||
.map_err(|e| e.to_string())?;
|
||||
|
||||
let messages: Vec<Message> = checks
|
||||
let messages: Vec<ExpandedMessage> = checks
|
||||
.into_iter()
|
||||
.map(|check| Message {
|
||||
.map(|check| ExpandedMessage {
|
||||
code: check.kind.code().clone(),
|
||||
message: check.kind.body(),
|
||||
location: check.location,
|
||||
end_location: check.end_location,
|
||||
fix: check.fix,
|
||||
fix: check.fix.map(|fix| ExpandedFix {
|
||||
content: fix.content,
|
||||
message: check.kind.commit(),
|
||||
location: fix.location,
|
||||
end_location: fix.end_location,
|
||||
}),
|
||||
})
|
||||
.collect();
|
||||
|
||||
@@ -200,7 +213,7 @@ mod test {
|
||||
check!(
|
||||
"if (1, 2): pass",
|
||||
r#"{}"#,
|
||||
[Message {
|
||||
[ExpandedMessage {
|
||||
code: CheckCode::F634,
|
||||
message: "If test is a tuple, which is always `True`".to_string(),
|
||||
location: Location::new(1, 0),
|
||||
|
||||
@@ -510,7 +510,7 @@ pub fn test_path(path: &Path, settings: &Settings) -> Result<Vec<Check>> {
|
||||
&locator,
|
||||
directives::Flags::from_settings(settings),
|
||||
);
|
||||
check_path(
|
||||
let mut checks = check_path(
|
||||
path,
|
||||
None,
|
||||
&contents,
|
||||
@@ -521,5 +521,52 @@ pub fn test_path(path: &Path, settings: &Settings) -> Result<Vec<Check>> {
|
||||
settings,
|
||||
flags::Autofix::Enabled,
|
||||
flags::Noqa::Enabled,
|
||||
)
|
||||
)?;
|
||||
|
||||
// Detect autofixes that don't converge after multiple iterations.
|
||||
if checks.iter().any(|check| check.fix.is_some()) {
|
||||
let max_iterations = 3;
|
||||
|
||||
let mut contents = contents.clone();
|
||||
let mut iterations = 0;
|
||||
|
||||
loop {
|
||||
let tokens: Vec<LexResult> = rustpython_helpers::tokenize(&contents);
|
||||
let locator = SourceCodeLocator::new(&contents);
|
||||
let stylist = SourceCodeStyleDetector::from_contents(&contents, &locator);
|
||||
let directives = directives::extract_directives(
|
||||
&tokens,
|
||||
&locator,
|
||||
directives::Flags::from_settings(settings),
|
||||
);
|
||||
let checks = check_path(
|
||||
path,
|
||||
None,
|
||||
&contents,
|
||||
tokens,
|
||||
&locator,
|
||||
&stylist,
|
||||
&directives,
|
||||
settings,
|
||||
flags::Autofix::Enabled,
|
||||
flags::Noqa::Enabled,
|
||||
)?;
|
||||
if let Some((fixed_contents, _)) = fix_file(&checks, &locator) {
|
||||
if iterations < max_iterations {
|
||||
iterations += 1;
|
||||
contents = fixed_contents.to_string();
|
||||
} else {
|
||||
panic!(
|
||||
"Failed to converge after {max_iterations} iterations. This likely \
|
||||
indicates a bug in the implementation of the fix."
|
||||
);
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
checks.sort_by_key(|check| check.location);
|
||||
Ok(checks)
|
||||
}
|
||||
|
||||
@@ -17,14 +17,13 @@ mod tests {
|
||||
#[test_case(10)]
|
||||
fn max_complexity_zero(max_complexity: usize) -> Result<()> {
|
||||
let snapshot = format!("max_complexity_{max_complexity}");
|
||||
let mut checks = test_path(
|
||||
let checks = test_path(
|
||||
Path::new("./resources/test/fixtures/mccabe/C901.py"),
|
||||
&Settings {
|
||||
mccabe: mccabe::settings::Settings { max_complexity },
|
||||
..Settings::for_rules(vec![CheckCode::C901])
|
||||
},
|
||||
)?;
|
||||
checks.sort_by_key(|check| check.location);
|
||||
insta::assert_yaml_snapshot!(snapshot, checks);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ mod tests {
|
||||
&locator,
|
||||
directives::Flags::from_settings(&settings),
|
||||
);
|
||||
let mut checks = check_path(
|
||||
let checks = check_path(
|
||||
Path::new("<filename>"),
|
||||
None,
|
||||
&contents,
|
||||
@@ -40,7 +40,6 @@ mod tests {
|
||||
flags::Autofix::Enabled,
|
||||
flags::Noqa::Enabled,
|
||||
)?;
|
||||
checks.sort_by_key(|check| check.location);
|
||||
let actual = checks
|
||||
.iter()
|
||||
.map(|check| check.kind.code().clone())
|
||||
|
||||
@@ -246,6 +246,7 @@ pub fn error_suffix_on_exception_name(
|
||||
class_def: &Stmt,
|
||||
bases: &[Expr],
|
||||
name: &str,
|
||||
locator: &SourceCodeLocator,
|
||||
) -> Option<Check> {
|
||||
if !bases.iter().any(|base| {
|
||||
if let ExprKind::Name { id, .. } = &base.node {
|
||||
@@ -262,6 +263,6 @@ pub fn error_suffix_on_exception_name(
|
||||
}
|
||||
Some(Check::new(
|
||||
CheckKind::ErrorSuffixOnExceptionName(name.to_string()),
|
||||
Range::from_located(class_def),
|
||||
identifier_range(class_def, locator),
|
||||
))
|
||||
}
|
||||
|
||||
@@ -32,13 +32,12 @@ mod tests {
|
||||
#[test_case(CheckCode::N818, Path::new("N818.py"); "N818")]
|
||||
fn checks(check_code: CheckCode, path: &Path) -> Result<()> {
|
||||
let snapshot = format!("{}_{}", check_code.as_ref(), path.to_string_lossy());
|
||||
let mut checks = test_path(
|
||||
let checks = test_path(
|
||||
Path::new("./resources/test/fixtures/pep8_naming")
|
||||
.join(path)
|
||||
.as_path(),
|
||||
&settings::Settings::for_rule(check_code),
|
||||
)?;
|
||||
checks.sort_by_key(|check| check.location);
|
||||
insta::assert_yaml_snapshot!(snapshot, checks);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -6,20 +6,20 @@ expression: checks
|
||||
ErrorSuffixOnExceptionName: C
|
||||
location:
|
||||
row: 9
|
||||
column: 0
|
||||
column: 6
|
||||
end_location:
|
||||
row: 10
|
||||
column: 8
|
||||
row: 9
|
||||
column: 7
|
||||
fix: ~
|
||||
parent: ~
|
||||
- kind:
|
||||
ErrorSuffixOnExceptionName: E
|
||||
location:
|
||||
row: 17
|
||||
column: 0
|
||||
column: 6
|
||||
end_location:
|
||||
row: 18
|
||||
column: 8
|
||||
row: 17
|
||||
column: 7
|
||||
fix: ~
|
||||
parent: ~
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ use rustpython_parser::ast::Location;
|
||||
use serde::Serialize;
|
||||
use serde_json::json;
|
||||
|
||||
use crate::autofix::{fixer, Fix};
|
||||
use crate::autofix::fixer;
|
||||
use crate::checks::CheckCode;
|
||||
use crate::fs::relativize_path;
|
||||
use crate::linter::Diagnostics;
|
||||
@@ -25,11 +25,19 @@ pub enum Violations {
|
||||
Hide,
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
struct ExpandedFix<'a> {
|
||||
content: &'a str,
|
||||
message: Option<String>,
|
||||
location: &'a Location,
|
||||
end_location: &'a Location,
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
struct ExpandedMessage<'a> {
|
||||
code: &'a CheckCode,
|
||||
message: String,
|
||||
fix: Option<&'a Fix>,
|
||||
fix: Option<ExpandedFix<'a>>,
|
||||
location: Location,
|
||||
end_location: Location,
|
||||
filename: &'a str,
|
||||
@@ -127,7 +135,12 @@ impl<'a> Printer<'a> {
|
||||
.map(|message| ExpandedMessage {
|
||||
code: message.kind.code(),
|
||||
message: message.kind.body(),
|
||||
fix: message.fix.as_ref(),
|
||||
fix: message.fix.as_ref().map(|fix| ExpandedFix {
|
||||
content: &fix.content,
|
||||
location: &fix.location,
|
||||
end_location: &fix.end_location,
|
||||
message: message.kind.commit(),
|
||||
}),
|
||||
location: message.location,
|
||||
end_location: message.end_location,
|
||||
filename: &message.filename,
|
||||
@@ -323,6 +336,17 @@ fn print_message(message: &Message) {
|
||||
);
|
||||
println!("{label}");
|
||||
if let Some(source) = &message.source {
|
||||
let commit = message.kind.commit();
|
||||
let footer = if commit.is_some() {
|
||||
vec![Annotation {
|
||||
id: None,
|
||||
label: commit.as_deref(),
|
||||
annotation_type: AnnotationType::Help,
|
||||
}]
|
||||
} else {
|
||||
vec![]
|
||||
};
|
||||
|
||||
let snippet = Snippet {
|
||||
title: Some(Annotation {
|
||||
label: None,
|
||||
@@ -330,7 +354,7 @@ fn print_message(message: &Message) {
|
||||
// The ID (error number) is already encoded in the `label`.
|
||||
id: None,
|
||||
}),
|
||||
footer: vec![],
|
||||
footer,
|
||||
slices: vec![Slice {
|
||||
source: &source.contents,
|
||||
line_start: message.location.row(),
|
||||
@@ -352,7 +376,7 @@ fn print_message(message: &Message) {
|
||||
// Skip the first line, since we format the `label` ourselves.
|
||||
let message = DisplayList::from(snippet).to_string();
|
||||
let (_, message) = message.split_once('\n').unwrap();
|
||||
println!("{message}");
|
||||
println!("{message}\n");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -371,6 +395,17 @@ fn print_grouped_message(message: &Message, row_length: usize, column_length: us
|
||||
);
|
||||
println!("{label}");
|
||||
if let Some(source) = &message.source {
|
||||
let commit = message.kind.commit();
|
||||
let footer = if commit.is_some() {
|
||||
vec![Annotation {
|
||||
id: None,
|
||||
label: commit.as_deref(),
|
||||
annotation_type: AnnotationType::Help,
|
||||
}]
|
||||
} else {
|
||||
vec![]
|
||||
};
|
||||
|
||||
let snippet = Snippet {
|
||||
title: Some(Annotation {
|
||||
label: None,
|
||||
@@ -378,7 +413,7 @@ fn print_grouped_message(message: &Message, row_length: usize, column_length: us
|
||||
// The ID (error number) is already encoded in the `label`.
|
||||
id: None,
|
||||
}),
|
||||
footer: vec![],
|
||||
footer,
|
||||
slices: vec![Slice {
|
||||
source: &source.contents,
|
||||
line_start: message.location.row(),
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
use itertools::izip;
|
||||
use once_cell::sync::Lazy;
|
||||
use regex::Regex;
|
||||
use rustpython_ast::{Constant, Located, Location, Stmt, StmtKind};
|
||||
use rustpython_ast::{Constant, Excepthandler, Location, Stmt, StmtKind};
|
||||
use rustpython_parser::ast::{Cmpop, Expr, ExprKind};
|
||||
|
||||
use crate::ast::helpers::except_range;
|
||||
use crate::ast::types::Range;
|
||||
use crate::autofix::Fix;
|
||||
use crate::checks::{Check, CheckKind};
|
||||
@@ -88,14 +89,18 @@ pub fn type_comparison(ops: &[Cmpop], comparators: &[Expr], location: Range) ->
|
||||
pub fn do_not_use_bare_except(
|
||||
type_: Option<&Expr>,
|
||||
body: &[Stmt],
|
||||
location: Range,
|
||||
handler: &Excepthandler,
|
||||
locator: &SourceCodeLocator,
|
||||
) -> Option<Check> {
|
||||
if type_.is_none()
|
||||
&& !body
|
||||
.iter()
|
||||
.any(|stmt| matches!(stmt.node, StmtKind::Raise { exc: None, .. }))
|
||||
{
|
||||
Some(Check::new(CheckKind::DoNotUseBareExcept, location))
|
||||
Some(Check::new(
|
||||
CheckKind::DoNotUseBareExcept,
|
||||
except_range(handler, locator),
|
||||
))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
@@ -106,11 +111,11 @@ fn is_ambiguous_name(name: &str) -> bool {
|
||||
}
|
||||
|
||||
/// E741
|
||||
pub fn ambiguous_variable_name<T>(name: &str, located: &Located<T>) -> Option<Check> {
|
||||
pub fn ambiguous_variable_name(name: &str, range: Range) -> Option<Check> {
|
||||
if is_ambiguous_name(name) {
|
||||
Some(Check::new(
|
||||
CheckKind::AmbiguousVariableName(name.to_string()),
|
||||
Range::from_located(located),
|
||||
range,
|
||||
))
|
||||
} else {
|
||||
None
|
||||
|
||||
@@ -37,24 +37,22 @@ mod tests {
|
||||
#[test_case(CheckCode::W605, Path::new("W605_1.py"))]
|
||||
fn checks(check_code: CheckCode, path: &Path) -> Result<()> {
|
||||
let snapshot = format!("{}_{}", check_code.as_ref(), path.to_string_lossy());
|
||||
let mut checks = test_path(
|
||||
let checks = test_path(
|
||||
Path::new("./resources/test/fixtures/pycodestyle")
|
||||
.join(path)
|
||||
.as_path(),
|
||||
&settings::Settings::for_rule(check_code),
|
||||
)?;
|
||||
checks.sort_by_key(|check| check.location);
|
||||
insta::assert_yaml_snapshot!(snapshot, checks);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn constant_literals() -> Result<()> {
|
||||
let mut checks = test_path(
|
||||
let checks = test_path(
|
||||
Path::new("./resources/test/fixtures/pycodestyle/constant_literals.py"),
|
||||
&settings::Settings::for_rules(vec![CheckCode::E711, CheckCode::E712, CheckCode::F632]),
|
||||
)?;
|
||||
checks.sort_by_key(|check| check.location);
|
||||
insta::assert_yaml_snapshot!(checks);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ use crate::ast::types::Range;
|
||||
use crate::ast::whitespace::leading_space;
|
||||
use crate::autofix::Fix;
|
||||
use crate::checkers::ast::Checker;
|
||||
use crate::checks::{Check, CheckKind, RejectedCmpop};
|
||||
use crate::checks::{Check, CheckKind};
|
||||
use crate::source_code_generator::SourceCodeGenerator;
|
||||
use crate::source_code_style::SourceCodeStyleDetector;
|
||||
|
||||
@@ -30,7 +30,11 @@ fn compare(
|
||||
comparators: comparators.to_vec(),
|
||||
},
|
||||
);
|
||||
let mut generator = SourceCodeGenerator::new(stylist.indentation(), stylist.quote());
|
||||
let mut generator = SourceCodeGenerator::new(
|
||||
stylist.indentation(),
|
||||
stylist.quote(),
|
||||
stylist.line_ending(),
|
||||
);
|
||||
generator.unparse_expr(&cmp, 0);
|
||||
generator.generate().ok()
|
||||
}
|
||||
@@ -68,7 +72,7 @@ pub fn literal_comparisons(
|
||||
{
|
||||
if matches!(op, Cmpop::Eq) {
|
||||
let check = Check::new(
|
||||
CheckKind::NoneComparison(RejectedCmpop::Eq),
|
||||
CheckKind::NoneComparison(op.into()),
|
||||
Range::from_located(comparator),
|
||||
);
|
||||
if checker.patch(check.kind.code()) && !helpers::is_constant_non_singleton(next) {
|
||||
@@ -78,7 +82,7 @@ pub fn literal_comparisons(
|
||||
}
|
||||
if matches!(op, Cmpop::NotEq) {
|
||||
let check = Check::new(
|
||||
CheckKind::NoneComparison(RejectedCmpop::NotEq),
|
||||
CheckKind::NoneComparison(op.into()),
|
||||
Range::from_located(comparator),
|
||||
);
|
||||
if checker.patch(check.kind.code()) && !helpers::is_constant_non_singleton(next) {
|
||||
@@ -96,7 +100,7 @@ pub fn literal_comparisons(
|
||||
{
|
||||
if matches!(op, Cmpop::Eq) {
|
||||
let check = Check::new(
|
||||
CheckKind::TrueFalseComparison(value, RejectedCmpop::Eq),
|
||||
CheckKind::TrueFalseComparison(value, op.into()),
|
||||
Range::from_located(comparator),
|
||||
);
|
||||
if checker.patch(check.kind.code()) && !helpers::is_constant_non_singleton(next) {
|
||||
@@ -106,7 +110,7 @@ pub fn literal_comparisons(
|
||||
}
|
||||
if matches!(op, Cmpop::NotEq) {
|
||||
let check = Check::new(
|
||||
CheckKind::TrueFalseComparison(value, RejectedCmpop::NotEq),
|
||||
CheckKind::TrueFalseComparison(value, op.into()),
|
||||
Range::from_located(comparator),
|
||||
);
|
||||
if checker.patch(check.kind.code()) && !helpers::is_constant_non_singleton(next) {
|
||||
@@ -130,7 +134,7 @@ pub fn literal_comparisons(
|
||||
{
|
||||
if matches!(op, Cmpop::Eq) {
|
||||
let check = Check::new(
|
||||
CheckKind::NoneComparison(RejectedCmpop::Eq),
|
||||
CheckKind::NoneComparison(op.into()),
|
||||
Range::from_located(next),
|
||||
);
|
||||
if checker.patch(check.kind.code())
|
||||
@@ -142,7 +146,7 @@ pub fn literal_comparisons(
|
||||
}
|
||||
if matches!(op, Cmpop::NotEq) {
|
||||
let check = Check::new(
|
||||
CheckKind::NoneComparison(RejectedCmpop::NotEq),
|
||||
CheckKind::NoneComparison(op.into()),
|
||||
Range::from_located(next),
|
||||
);
|
||||
if checker.patch(check.kind.code())
|
||||
@@ -162,7 +166,7 @@ pub fn literal_comparisons(
|
||||
{
|
||||
if matches!(op, Cmpop::Eq) {
|
||||
let check = Check::new(
|
||||
CheckKind::TrueFalseComparison(value, RejectedCmpop::Eq),
|
||||
CheckKind::TrueFalseComparison(value, op.into()),
|
||||
Range::from_located(next),
|
||||
);
|
||||
if checker.patch(check.kind.code())
|
||||
@@ -174,7 +178,7 @@ pub fn literal_comparisons(
|
||||
}
|
||||
if matches!(op, Cmpop::NotEq) {
|
||||
let check = Check::new(
|
||||
CheckKind::TrueFalseComparison(value, RejectedCmpop::NotEq),
|
||||
CheckKind::TrueFalseComparison(value, op.into()),
|
||||
Range::from_located(next),
|
||||
);
|
||||
if checker.patch(check.kind.code())
|
||||
@@ -302,7 +306,11 @@ fn function(
|
||||
type_comment: None,
|
||||
},
|
||||
);
|
||||
let mut generator = SourceCodeGenerator::new(stylist.indentation(), stylist.quote());
|
||||
let mut generator = SourceCodeGenerator::new(
|
||||
stylist.indentation(),
|
||||
stylist.quote(),
|
||||
stylist.line_ending(),
|
||||
);
|
||||
generator.unparse_stmt(&func);
|
||||
Ok(generator.generate()?)
|
||||
}
|
||||
@@ -311,7 +319,10 @@ fn function(
|
||||
pub fn do_not_assign_lambda(checker: &mut Checker, target: &Expr, value: &Expr, stmt: &Stmt) {
|
||||
if let ExprKind::Name { id, .. } = &target.node {
|
||||
if let ExprKind::Lambda { args, body } = &value.node {
|
||||
let mut check = Check::new(CheckKind::DoNotAssignLambda, Range::from_located(stmt));
|
||||
let mut check = Check::new(
|
||||
CheckKind::DoNotAssignLambda(id.to_string()),
|
||||
Range::from_located(stmt),
|
||||
);
|
||||
if checker.patch(check.kind.code()) {
|
||||
if !match_leading_content(stmt, checker.locator)
|
||||
&& !match_trailing_content(stmt, checker.locator)
|
||||
|
||||
@@ -7,8 +7,8 @@ expression: checks
|
||||
row: 4
|
||||
column: 0
|
||||
end_location:
|
||||
row: 5
|
||||
column: 8
|
||||
row: 4
|
||||
column: 6
|
||||
fix: ~
|
||||
parent: ~
|
||||
- kind: DoNotUseBareExcept
|
||||
@@ -16,8 +16,8 @@ expression: checks
|
||||
row: 11
|
||||
column: 0
|
||||
end_location:
|
||||
row: 12
|
||||
column: 8
|
||||
row: 11
|
||||
column: 6
|
||||
fix: ~
|
||||
parent: ~
|
||||
- kind: DoNotUseBareExcept
|
||||
@@ -25,8 +25,8 @@ expression: checks
|
||||
row: 16
|
||||
column: 0
|
||||
end_location:
|
||||
row: 17
|
||||
column: 8
|
||||
row: 16
|
||||
column: 6
|
||||
fix: ~
|
||||
parent: ~
|
||||
|
||||
|
||||
@@ -2,7 +2,8 @@
|
||||
source: src/pycodestyle/mod.rs
|
||||
expression: checks
|
||||
---
|
||||
- kind: DoNotAssignLambda
|
||||
- kind:
|
||||
DoNotAssignLambda: f
|
||||
location:
|
||||
row: 2
|
||||
column: 0
|
||||
@@ -18,7 +19,8 @@ expression: checks
|
||||
row: 2
|
||||
column: 19
|
||||
parent: ~
|
||||
- kind: DoNotAssignLambda
|
||||
- kind:
|
||||
DoNotAssignLambda: f
|
||||
location:
|
||||
row: 4
|
||||
column: 0
|
||||
@@ -34,7 +36,8 @@ expression: checks
|
||||
row: 4
|
||||
column: 19
|
||||
parent: ~
|
||||
- kind: DoNotAssignLambda
|
||||
- kind:
|
||||
DoNotAssignLambda: this
|
||||
location:
|
||||
row: 7
|
||||
column: 4
|
||||
|
||||
@@ -106,7 +106,7 @@ expression: checks
|
||||
AmbiguousVariableName: l
|
||||
location:
|
||||
row: 25
|
||||
column: 4
|
||||
column: 11
|
||||
end_location:
|
||||
row: 25
|
||||
column: 12
|
||||
@@ -136,7 +136,7 @@ expression: checks
|
||||
AmbiguousVariableName: l
|
||||
location:
|
||||
row: 33
|
||||
column: 8
|
||||
column: 17
|
||||
end_location:
|
||||
row: 33
|
||||
column: 18
|
||||
@@ -236,10 +236,10 @@ expression: checks
|
||||
AmbiguousVariableName: l
|
||||
location:
|
||||
row: 71
|
||||
column: 0
|
||||
column: 21
|
||||
end_location:
|
||||
row: 72
|
||||
column: 8
|
||||
row: 71
|
||||
column: 22
|
||||
fix: ~
|
||||
parent: ~
|
||||
- kind:
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user