Compare commits
2 Commits
v0.0.261
...
charlie/ca
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2446cd49fa | ||
|
|
5f5e71e81d |
26
Cargo.lock
generated
26
Cargo.lock
generated
@@ -774,7 +774,7 @@ checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80"
|
||||
|
||||
[[package]]
|
||||
name = "flake8-to-ruff"
|
||||
version = "0.0.261"
|
||||
version = "0.0.260"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"clap 4.1.8",
|
||||
@@ -1977,7 +1977,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ruff"
|
||||
version = "0.0.261"
|
||||
version = "0.0.260"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bitflags",
|
||||
@@ -2010,7 +2010,6 @@ dependencies = [
|
||||
"ruff_diagnostics",
|
||||
"ruff_macros",
|
||||
"ruff_python_ast",
|
||||
"ruff_python_semantic",
|
||||
"ruff_python_stdlib",
|
||||
"ruff_rustpython",
|
||||
"rustc-hash",
|
||||
@@ -2060,7 +2059,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ruff_cli"
|
||||
version = "0.0.261"
|
||||
version = "0.0.260"
|
||||
dependencies = [
|
||||
"annotate-snippets 0.9.1",
|
||||
"anyhow",
|
||||
@@ -2088,7 +2087,6 @@ dependencies = [
|
||||
"ruff",
|
||||
"ruff_cache",
|
||||
"ruff_diagnostics",
|
||||
"ruff_python_ast",
|
||||
"ruff_python_stdlib",
|
||||
"rustc-hash",
|
||||
"serde",
|
||||
@@ -2171,15 +2169,16 @@ dependencies = [
|
||||
"is-macro",
|
||||
"itertools",
|
||||
"log",
|
||||
"nohash-hasher",
|
||||
"num-bigint",
|
||||
"num-traits",
|
||||
"once_cell",
|
||||
"regex",
|
||||
"ruff_python_stdlib",
|
||||
"ruff_rustpython",
|
||||
"rustc-hash",
|
||||
"rustpython-common",
|
||||
"rustpython-parser",
|
||||
"serde",
|
||||
"smallvec",
|
||||
]
|
||||
|
||||
@@ -2195,6 +2194,7 @@ dependencies = [
|
||||
"once_cell",
|
||||
"ruff_formatter",
|
||||
"ruff_python_ast",
|
||||
"ruff_python_stdlib",
|
||||
"ruff_rustpython",
|
||||
"ruff_testing_macros",
|
||||
"ruff_text_size",
|
||||
@@ -2205,20 +2205,6 @@ dependencies = [
|
||||
"test-case",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ruff_python_semantic"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"is-macro",
|
||||
"nohash-hasher",
|
||||
"ruff_python_ast",
|
||||
"ruff_python_stdlib",
|
||||
"rustc-hash",
|
||||
"rustpython-parser",
|
||||
"smallvec",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ruff_python_stdlib"
|
||||
version = "0.0.0"
|
||||
|
||||
@@ -24,7 +24,6 @@ is-macro = { version = "0.2.2" }
|
||||
itertools = { version = "0.10.5" }
|
||||
libcst = { git = "https://github.com/charliermarsh/LibCST", rev = "80e4c1399f95e5beb532fdd1e209ad2dbb470438" }
|
||||
log = { version = "0.4.17" }
|
||||
nohash-hasher = { version = "0.2.0" }
|
||||
once_cell = { version = "1.17.1" }
|
||||
path-absolutize = { version = "3.0.14" }
|
||||
proc-macro2 = { version = "1.0.51" }
|
||||
@@ -41,7 +40,6 @@ serde = { version = "1.0.152", features = ["derive"] }
|
||||
serde_json = { version = "1.0.93", features = ["preserve_order"] }
|
||||
shellexpand = { version = "3.0.0" }
|
||||
similar = { version = "2.2.1" }
|
||||
smallvec = { version = "1.10.0" }
|
||||
strum = { version = "0.24.1", features = ["strum_macros"] }
|
||||
strum_macros = { version = "0.24.3" }
|
||||
syn = { version = "1.0.109" }
|
||||
|
||||
19
README.md
19
README.md
@@ -137,7 +137,7 @@ Ruff can also be used as a [pre-commit](https://pre-commit.com) hook:
|
||||
```yaml
|
||||
- repo: https://github.com/charliermarsh/ruff-pre-commit
|
||||
# Ruff version.
|
||||
rev: 'v0.0.261'
|
||||
rev: 'v0.0.260'
|
||||
hooks:
|
||||
- id: ruff
|
||||
```
|
||||
@@ -145,20 +145,6 @@ Ruff can also be used as a [pre-commit](https://pre-commit.com) hook:
|
||||
Ruff can also be used as a [VS Code extension](https://github.com/charliermarsh/ruff-vscode) or
|
||||
alongside any other editor through the [Ruff LSP](https://github.com/charliermarsh/ruff-lsp).
|
||||
|
||||
Ruff can also be used as a [GitHub Action](https://github.com/features/actions) via
|
||||
[`ruff-action`](https://github.com/chartboost/ruff-action):
|
||||
|
||||
```yaml
|
||||
name: Ruff
|
||||
on: [ push, pull_request ]
|
||||
jobs:
|
||||
ruff:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: chartboost/ruff-action@v1
|
||||
```
|
||||
|
||||
### Configuration
|
||||
|
||||
Ruff can be configured through a `pyproject.toml`, `ruff.toml`, or `.ruff.toml` file (see:
|
||||
@@ -378,9 +364,6 @@ Ruff is used in a number of major open-source projects, including:
|
||||
- [Neon](https://github.com/neondatabase/neon)
|
||||
- [The Algorithms](https://github.com/TheAlgorithms/Python)
|
||||
- [Openverse](https://github.com/WordPress/openverse)
|
||||
- [MegaLinter](https://github.com/oxsecurity/megalinter)
|
||||
- [LangChain](https://github.com/hwchase17/langchain)
|
||||
- [LlamaIndex](https://github.com/jerryjliu/llama_index)
|
||||
|
||||
## License
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "flake8-to-ruff"
|
||||
version = "0.0.261"
|
||||
version = "0.0.260"
|
||||
edition = { workspace = true }
|
||||
rust-version = { workspace = true }
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "ruff"
|
||||
version = "0.0.261"
|
||||
version = "0.0.260"
|
||||
authors.workspace = true
|
||||
edition.workspace = true
|
||||
rust-version.workspace = true
|
||||
@@ -18,7 +18,6 @@ ruff_cache = { path = "../ruff_cache" }
|
||||
ruff_diagnostics = { path = "../ruff_diagnostics", features = ["serde"] }
|
||||
ruff_macros = { path = "../ruff_macros" }
|
||||
ruff_python_ast = { path = "../ruff_python_ast" }
|
||||
ruff_python_semantic = { path = "../ruff_python_semantic" }
|
||||
ruff_python_stdlib = { path = "../ruff_python_stdlib" }
|
||||
ruff_rustpython = { path = "../ruff_rustpython" }
|
||||
|
||||
@@ -38,7 +37,7 @@ itertools = { workspace = true }
|
||||
libcst = { workspace = true }
|
||||
log = { workspace = true }
|
||||
natord = { version = "1.0.9" }
|
||||
nohash-hasher = { workspace = true }
|
||||
nohash-hasher = { version = "0.2.0" }
|
||||
num-bigint = { version = "0.4.3" }
|
||||
num-traits = { version = "0.2.15" }
|
||||
once_cell = { workspace = true }
|
||||
@@ -58,7 +57,7 @@ semver = { version = "1.0.16" }
|
||||
serde = { workspace = true }
|
||||
serde_json = { workspace = true }
|
||||
shellexpand = { workspace = true }
|
||||
smallvec = { workspace = true }
|
||||
smallvec = { version = "1.10.0" }
|
||||
strum = { workspace = true }
|
||||
strum_macros = { workspace = true }
|
||||
textwrap = { workspace = true }
|
||||
|
||||
@@ -28,11 +28,6 @@ except (ValueError, *(RuntimeError, (KeyError, TypeError))): # error
|
||||
pass
|
||||
|
||||
|
||||
try:
|
||||
pass
|
||||
except (*a, *(RuntimeError, (KeyError, TypeError))): # error
|
||||
pass
|
||||
|
||||
try:
|
||||
pass
|
||||
except (ValueError, *(RuntimeError, TypeError)): # ok
|
||||
@@ -43,36 +38,10 @@ try:
|
||||
except (ValueError, *[RuntimeError, *(TypeError,)]): # ok
|
||||
pass
|
||||
|
||||
|
||||
try:
|
||||
pass
|
||||
except (*a, *b): # ok
|
||||
pass
|
||||
|
||||
|
||||
try:
|
||||
pass
|
||||
except (*a, *(RuntimeError, TypeError)): # ok
|
||||
pass
|
||||
|
||||
|
||||
try:
|
||||
pass
|
||||
except (*a, *(b, c)): # ok
|
||||
pass
|
||||
|
||||
|
||||
try:
|
||||
pass
|
||||
except (*a, *(*b, *c)): # ok
|
||||
pass
|
||||
|
||||
|
||||
def what_to_catch():
|
||||
return ...
|
||||
|
||||
|
||||
try:
|
||||
pass
|
||||
except what_to_catch(): # ok
|
||||
pass
|
||||
pass
|
||||
@@ -78,56 +78,6 @@ for _section, section_items in itertools.groupby(items, key=lambda p: p[1]):
|
||||
for shopper in shoppers:
|
||||
collect_shop_items(shopper, section_items) # B031
|
||||
|
||||
for _section, section_items in itertools.groupby(items, key=lambda p: p[1]):
|
||||
if _section == "greens":
|
||||
collect_shop_items(shopper, section_items)
|
||||
else:
|
||||
collect_shop_items(shopper, section_items)
|
||||
collect_shop_items(shopper, section_items) # B031
|
||||
|
||||
for _section, section_items in itertools.groupby(items, key=lambda p: p[1]):
|
||||
# Mutually exclusive branches shouldn't trigger the warning
|
||||
if _section == "greens":
|
||||
collect_shop_items(shopper, section_items)
|
||||
if _section == "greens":
|
||||
collect_shop_items(shopper, section_items) # B031
|
||||
elif _section == "frozen items":
|
||||
collect_shop_items(shopper, section_items) # B031
|
||||
else:
|
||||
collect_shop_items(shopper, section_items) # B031
|
||||
collect_shop_items(shopper, section_items) # B031
|
||||
elif _section == "frozen items":
|
||||
# Mix `match` and `if` statements
|
||||
match shopper:
|
||||
case "Jane":
|
||||
collect_shop_items(shopper, section_items)
|
||||
if _section == "fourth":
|
||||
collect_shop_items(shopper, section_items) # B031
|
||||
case _:
|
||||
collect_shop_items(shopper, section_items)
|
||||
else:
|
||||
collect_shop_items(shopper, section_items)
|
||||
# Now, it should detect
|
||||
collect_shop_items(shopper, section_items) # B031
|
||||
|
||||
for _section, section_items in itertools.groupby(items, key=lambda p: p[1]):
|
||||
# Mutually exclusive branches shouldn't trigger the warning
|
||||
match _section:
|
||||
case "greens":
|
||||
collect_shop_items(shopper, section_items)
|
||||
match shopper:
|
||||
case "Jane":
|
||||
collect_shop_items(shopper, section_items) # B031
|
||||
case _:
|
||||
collect_shop_items(shopper, section_items) # B031
|
||||
case "frozen items":
|
||||
collect_shop_items(shopper, section_items)
|
||||
collect_shop_items(shopper, section_items) # B031
|
||||
case _:
|
||||
collect_shop_items(shopper, section_items)
|
||||
# Now, it should detect
|
||||
collect_shop_items(shopper, section_items) # B031
|
||||
|
||||
for group in groupby(items, key=lambda p: p[1]):
|
||||
# This is bad, but not detected currently
|
||||
collect_shop_items("Jane", group[1])
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
import logging
|
||||
from distutils import log
|
||||
|
||||
logging.warn("Hello World!")
|
||||
log.warn("Hello world!") # This shouldn't be considered as a logger candidate
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import builtins
|
||||
import typing
|
||||
from typing import TypeAlias, Final, NewType, TypeVar, TypeVarTuple, ParamSpec
|
||||
from typing import TypeAlias, Final
|
||||
|
||||
# We shouldn't emit Y015 for simple default values
|
||||
field1: int
|
||||
@@ -26,10 +26,6 @@ field9 = None # Y026 Use typing_extensions.TypeAlias for type aliases, e.g. "fi
|
||||
Field95: TypeAlias = None
|
||||
Field96: TypeAlias = int | None
|
||||
Field97: TypeAlias = None | typing.SupportsInt | builtins.str | float | bool
|
||||
Field98 = NewType('MyInt', int)
|
||||
Field99 = TypeVar('Field99')
|
||||
Field100 = TypeVarTuple('Field100')
|
||||
Field101 = ParamSpec('Field101')
|
||||
field19 = [1, 2, 3] # Y052 Need type annotation for "field19"
|
||||
field191: list[int] = [1, 2, 3]
|
||||
field20 = (1, 2, 3) # Y052 Need type annotation for "field20"
|
||||
|
||||
@@ -9,17 +9,6 @@ os.environ.get('foo', 'bar')
|
||||
|
||||
os.getenv('foo')
|
||||
|
||||
env = os.environ.get('foo')
|
||||
|
||||
env = os.environ['foo']
|
||||
|
||||
if env := os.environ.get('foo'):
|
||||
pass
|
||||
|
||||
if env := os.environ['foo']:
|
||||
pass
|
||||
|
||||
|
||||
# Good
|
||||
os.environ['FOO']
|
||||
|
||||
@@ -28,13 +17,3 @@ os.environ.get('FOO')
|
||||
os.environ.get('FOO', 'bar')
|
||||
|
||||
os.getenv('FOO')
|
||||
|
||||
env = os.getenv('FOO')
|
||||
|
||||
if env := os.getenv('FOO'):
|
||||
pass
|
||||
|
||||
env = os.environ['FOO']
|
||||
|
||||
if env := os.environ['FOO']:
|
||||
pass
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
# SIM910
|
||||
{}.get(key, None)
|
||||
|
||||
# SIM910
|
||||
{}.get("key", None)
|
||||
|
||||
# OK
|
||||
{}.get(key)
|
||||
|
||||
# OK
|
||||
{}.get("key")
|
||||
|
||||
# OK
|
||||
{}.get(key, False)
|
||||
|
||||
# OK
|
||||
{}.get("key", False)
|
||||
|
||||
# SIM910
|
||||
if a := {}.get(key, None):
|
||||
pass
|
||||
|
||||
# SIM910
|
||||
a = {}.get(key, None)
|
||||
|
||||
# SIM910
|
||||
({}).get(key, None)
|
||||
@@ -1,4 +1,3 @@
|
||||
//! Interface for generating autofix edits from higher-level actions (e.g., "remove an argument").
|
||||
use anyhow::{bail, Result};
|
||||
use itertools::Itertools;
|
||||
use libcst_native::{
|
||||
@@ -8,12 +7,12 @@ use rustpython_parser::ast::{ExcepthandlerKind, Expr, Keyword, Location, Stmt, S
|
||||
use rustpython_parser::{lexer, Mode, Tok};
|
||||
|
||||
use ruff_diagnostics::Edit;
|
||||
use ruff_python_ast::context::Context;
|
||||
use ruff_python_ast::helpers;
|
||||
use ruff_python_ast::helpers::to_absolute;
|
||||
use ruff_python_ast::imports::{AnyImport, Import};
|
||||
use ruff_python_ast::newlines::NewlineWithTrailingNewline;
|
||||
use ruff_python_ast::source_code::{Indexer, Locator, Stylist};
|
||||
use ruff_python_semantic::context::Context;
|
||||
|
||||
use crate::cst::helpers::compose_module_path;
|
||||
use crate::cst::matchers::match_module;
|
||||
@@ -532,7 +531,7 @@ mod tests {
|
||||
|
||||
use ruff_python_ast::source_code::Locator;
|
||||
|
||||
use crate::autofix::actions::{next_stmt_break, trailing_semicolon};
|
||||
use crate::autofix::helpers::{next_stmt_break, trailing_semicolon};
|
||||
|
||||
#[test]
|
||||
fn find_semicolon() -> Result<()> {
|
||||
@@ -11,7 +11,7 @@ use ruff_python_ast::types::Range;
|
||||
use crate::linter::FixTable;
|
||||
use crate::registry::{AsRule, Rule};
|
||||
|
||||
pub mod actions;
|
||||
pub mod helpers;
|
||||
|
||||
/// Auto-fix errors in a file, and write the fixed source code to disk.
|
||||
pub fn fix_file(diagnostics: &[Diagnostic], locator: &Locator) -> Option<(String, FixTable)> {
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
use ruff_python_semantic::scope::ScopeStack;
|
||||
use ruff_python_ast::scope::ScopeStack;
|
||||
use rustpython_parser::ast::{Expr, Stmt};
|
||||
|
||||
use ruff_python_ast::types::Range;
|
||||
use ruff_python_ast::types::RefEquality;
|
||||
use ruff_python_semantic::analyze::visibility::{Visibility, VisibleScope};
|
||||
use ruff_python_ast::visibility::{Visibility, VisibleScope};
|
||||
|
||||
use crate::checkers::ast::AnnotationContext;
|
||||
use crate::docstrings::definition::Definition;
|
||||
|
||||
@@ -14,22 +14,22 @@ use rustpython_parser::ast::{
|
||||
|
||||
use ruff_diagnostics::Diagnostic;
|
||||
use ruff_python_ast::all::{extract_all_names, AllNamesFlags};
|
||||
use ruff_python_ast::helpers::{extract_handled_exceptions, to_module_path};
|
||||
use ruff_python_ast::source_code::{Indexer, Locator, Stylist};
|
||||
use ruff_python_ast::types::{Node, Range, RefEquality};
|
||||
use ruff_python_ast::typing::parse_type_annotation;
|
||||
use ruff_python_ast::visitor::{walk_excepthandler, walk_pattern, Visitor};
|
||||
use ruff_python_ast::{branch_detection, cast, helpers, str, visitor};
|
||||
use ruff_python_semantic::analyze;
|
||||
use ruff_python_semantic::analyze::typing::{Callable, SubscriptKind};
|
||||
use ruff_python_semantic::binding::{
|
||||
use ruff_python_ast::binding::{
|
||||
Binding, BindingId, BindingKind, Exceptions, ExecutionContext, Export, FromImportation,
|
||||
Importation, StarImportation, SubmoduleImportation,
|
||||
};
|
||||
use ruff_python_semantic::context::Context;
|
||||
use ruff_python_semantic::scope::{
|
||||
use ruff_python_ast::context::Context;
|
||||
use ruff_python_ast::helpers::{extract_handled_exceptions, to_module_path};
|
||||
use ruff_python_ast::scope::{
|
||||
ClassDef, FunctionDef, Lambda, Scope, ScopeId, ScopeKind, ScopeStack,
|
||||
};
|
||||
use ruff_python_ast::source_code::{Indexer, Locator, Stylist};
|
||||
use ruff_python_ast::types::{Node, Range, RefEquality};
|
||||
use ruff_python_ast::typing::{
|
||||
match_annotated_subscript, parse_type_annotation, Callable, SubscriptKind,
|
||||
};
|
||||
use ruff_python_ast::visitor::{walk_excepthandler, walk_pattern, Visitor};
|
||||
use ruff_python_ast::{branch_detection, cast, helpers, str, typing, visibility, visitor};
|
||||
use ruff_python_stdlib::builtins::{BUILTINS, MAGIC_GLOBALS};
|
||||
use ruff_python_stdlib::path::is_python_stub_file;
|
||||
|
||||
@@ -1847,6 +1847,13 @@ where
|
||||
if self.settings.rules.enabled(Rule::UselessExpression) {
|
||||
flake8_bugbear::rules::useless_expression(self, value);
|
||||
}
|
||||
if self
|
||||
.settings
|
||||
.rules
|
||||
.enabled(Rule::UncapitalizedEnvironmentVariables)
|
||||
{
|
||||
flake8_simplify::rules::use_capital_environment_variables(self, value);
|
||||
}
|
||||
if self.settings.rules.enabled(Rule::AsyncioDanglingTask) {
|
||||
if let Some(diagnostic) = ruff::rules::asyncio_dangling_task(value, |expr| {
|
||||
self.ctx.resolve_call_path(expr)
|
||||
@@ -2203,14 +2210,6 @@ where
|
||||
]) {
|
||||
flake8_2020::rules::subscript(self, value, slice);
|
||||
}
|
||||
|
||||
if self
|
||||
.settings
|
||||
.rules
|
||||
.enabled(Rule::UncapitalizedEnvironmentVariables)
|
||||
{
|
||||
flake8_simplify::rules::use_capital_environment_variables(self, expr);
|
||||
}
|
||||
}
|
||||
ExprKind::Tuple { elts, ctx } | ExprKind::List { elts, ctx } => {
|
||||
if matches!(ctx, ExprContext::Store) {
|
||||
@@ -2249,7 +2248,7 @@ where
|
||||
|| (self.settings.target_version >= PythonVersion::Py37
|
||||
&& self.ctx.annotations_future_enabled
|
||||
&& self.ctx.in_annotation))
|
||||
&& analyze::typing::is_pep585_builtin(expr, &self.ctx)
|
||||
&& typing::is_pep585_builtin(expr, &self.ctx)
|
||||
{
|
||||
pyupgrade::rules::use_pep585_annotation(self, expr);
|
||||
}
|
||||
@@ -2292,7 +2291,7 @@ where
|
||||
|| (self.settings.target_version >= PythonVersion::Py37
|
||||
&& self.ctx.annotations_future_enabled
|
||||
&& self.ctx.in_annotation))
|
||||
&& analyze::typing::is_pep585_builtin(expr, &self.ctx)
|
||||
&& typing::is_pep585_builtin(expr, &self.ctx)
|
||||
{
|
||||
pyupgrade::rules::use_pep585_annotation(self, expr);
|
||||
}
|
||||
@@ -2911,14 +2910,6 @@ where
|
||||
}
|
||||
|
||||
// flake8-simplify
|
||||
if self
|
||||
.settings
|
||||
.rules
|
||||
.enabled(Rule::UncapitalizedEnvironmentVariables)
|
||||
{
|
||||
flake8_simplify::rules::use_capital_environment_variables(self, expr);
|
||||
}
|
||||
|
||||
if self
|
||||
.settings
|
||||
.rules
|
||||
@@ -2927,10 +2918,6 @@ where
|
||||
flake8_simplify::rules::open_file_with_context_handler(self, func);
|
||||
}
|
||||
|
||||
if self.settings.rules.enabled(Rule::DictGetWithNoneDefault) {
|
||||
flake8_simplify::rules::dict_get_with_none_default(self, expr);
|
||||
}
|
||||
|
||||
// flake8-use-pathlib
|
||||
if self.settings.rules.any_enabled(&[
|
||||
Rule::OsPathAbspath,
|
||||
@@ -3641,7 +3628,7 @@ where
|
||||
self.ctx.in_subscript = true;
|
||||
visitor::walk_expr(self, expr);
|
||||
} else {
|
||||
match analyze::typing::match_annotated_subscript(
|
||||
match match_annotated_subscript(
|
||||
value,
|
||||
&self.ctx,
|
||||
self.settings.typing_modules.iter().map(String::as_str),
|
||||
@@ -4060,7 +4047,7 @@ impl<'a> Checker<'a> {
|
||||
&& binding.redefines(existing)
|
||||
&& (!self.settings.dummy_variable_rgx.is_match(name) || existing_is_import)
|
||||
&& !(existing.kind.is_function_definition()
|
||||
&& analyze::visibility::is_overload(
|
||||
&& visibility::is_overload(
|
||||
&self.ctx,
|
||||
cast::decorator_list(existing.source.as_ref().unwrap()),
|
||||
))
|
||||
@@ -4094,7 +4081,7 @@ impl<'a> Checker<'a> {
|
||||
}
|
||||
} else if existing_is_import && binding.redefines(existing) {
|
||||
self.ctx
|
||||
.shadowed_bindings
|
||||
.redefinitions
|
||||
.entry(existing_binding_index)
|
||||
.or_insert_with(Vec::new)
|
||||
.push(binding_id);
|
||||
@@ -4136,7 +4123,13 @@ impl<'a> Checker<'a> {
|
||||
// in scope.
|
||||
let scope = self.ctx.scope_mut();
|
||||
if !(binding.kind.is_annotation() && scope.defines(name)) {
|
||||
scope.add(name, binding_id);
|
||||
if let Some(rebound_index) = scope.add(name, binding_id) {
|
||||
scope
|
||||
.rebounds
|
||||
.entry(name)
|
||||
.or_insert_with(Vec::new)
|
||||
.push(rebound_index);
|
||||
}
|
||||
}
|
||||
|
||||
self.ctx.bindings.push(binding);
|
||||
@@ -4459,23 +4452,7 @@ impl<'a> Checker<'a> {
|
||||
}
|
||||
_ => false,
|
||||
} {
|
||||
let (all_names, all_names_flags) = {
|
||||
let (mut names, flags) =
|
||||
extract_all_names(parent, |name| self.ctx.is_builtin(name));
|
||||
|
||||
// Grab the existing bound __all__ values.
|
||||
if let StmtKind::AugAssign { .. } = &parent.node {
|
||||
if let Some(index) = current.get("__all__") {
|
||||
if let BindingKind::Export(Export { names: existing }) =
|
||||
&self.ctx.bindings[*index].kind
|
||||
{
|
||||
names.extend_from_slice(existing);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
(names, flags)
|
||||
};
|
||||
let (all_names, all_names_flags) = extract_all_names(&self.ctx, parent, current);
|
||||
|
||||
if self.settings.rules.enabled(Rule::InvalidAllFormat) {
|
||||
if matches!(all_names_flags, AllNamesFlags::INVALID_FORMAT) {
|
||||
@@ -4772,7 +4749,7 @@ impl<'a> Checker<'a> {
|
||||
// Mark anything referenced in `__all__` as used.
|
||||
let all_bindings: Option<(Vec<BindingId>, Range)> = {
|
||||
let global_scope = self.ctx.global_scope();
|
||||
let all_names: Option<(&Vec<&str>, Range)> = global_scope
|
||||
let all_names: Option<(&Vec<String>, Range)> = global_scope
|
||||
.get("__all__")
|
||||
.map(|index| &self.ctx.bindings[*index])
|
||||
.and_then(|binding| match &binding.kind {
|
||||
@@ -4784,7 +4761,7 @@ impl<'a> Checker<'a> {
|
||||
(
|
||||
names
|
||||
.iter()
|
||||
.filter_map(|name| global_scope.get(name).copied())
|
||||
.filter_map(|name| global_scope.get(name.as_str()).copied())
|
||||
.collect(),
|
||||
range,
|
||||
)
|
||||
@@ -4802,13 +4779,15 @@ impl<'a> Checker<'a> {
|
||||
}
|
||||
|
||||
// Extract `__all__` names from the global scope.
|
||||
let all_names: Option<(&[&str], Range)> = self
|
||||
let all_names: Option<(Vec<&str>, Range)> = self
|
||||
.ctx
|
||||
.global_scope()
|
||||
.get("__all__")
|
||||
.map(|index| &self.ctx.bindings[*index])
|
||||
.and_then(|binding| match &binding.kind {
|
||||
BindingKind::Export(Export { names }) => Some((names.as_slice(), binding.range)),
|
||||
BindingKind::Export(Export { names }) => {
|
||||
Some((names.iter().map(String::as_str).collect(), binding.range))
|
||||
}
|
||||
_ => None,
|
||||
});
|
||||
|
||||
@@ -4868,7 +4847,7 @@ impl<'a> Checker<'a> {
|
||||
.dedup()
|
||||
.collect();
|
||||
if !sources.is_empty() {
|
||||
for &name in names.iter() {
|
||||
for &name in names {
|
||||
if !scope.defines(name) {
|
||||
diagnostics.push(Diagnostic::new(
|
||||
pyflakes::rules::UndefinedLocalWithImportStarUsage {
|
||||
@@ -4926,7 +4905,7 @@ impl<'a> Checker<'a> {
|
||||
continue;
|
||||
}
|
||||
|
||||
if let Some(indices) = self.ctx.shadowed_bindings.get(index) {
|
||||
if let Some(indices) = self.ctx.redefinitions.get(index) {
|
||||
for index in indices {
|
||||
let rebound = &self.ctx.bindings[*index];
|
||||
let mut diagnostic = Diagnostic::new(
|
||||
@@ -5073,7 +5052,7 @@ impl<'a> Checker<'a> {
|
||||
|
||||
let fix = if !in_init && !in_except_handler && self.patch(Rule::UnusedImport) {
|
||||
let deleted: Vec<&Stmt> = self.deletions.iter().map(Into::into).collect();
|
||||
match autofix::actions::remove_unused_imports(
|
||||
match autofix::helpers::remove_unused_imports(
|
||||
unused_imports.iter().map(|(full_name, _)| *full_name),
|
||||
child,
|
||||
parent,
|
||||
|
||||
@@ -1,12 +1,10 @@
|
||||
//! Lint rules based on import analysis.
|
||||
use std::borrow::Cow;
|
||||
|
||||
use std::path::Path;
|
||||
|
||||
use rustpython_parser::ast::{StmtKind, Suite};
|
||||
use rustpython_parser::ast::Suite;
|
||||
|
||||
use ruff_diagnostics::Diagnostic;
|
||||
use ruff_python_ast::helpers::to_module_path;
|
||||
use ruff_python_ast::imports::{ImportMap, ModuleImport};
|
||||
use ruff_python_ast::source_code::{Indexer, Locator, Stylist};
|
||||
use ruff_python_ast::visitor::Visitor;
|
||||
|
||||
@@ -16,66 +14,6 @@ use crate::rules::isort;
|
||||
use crate::rules::isort::track::{Block, ImportTracker};
|
||||
use crate::settings::{flags, Settings};
|
||||
|
||||
fn extract_import_map(path: &Path, package: Option<&Path>, blocks: &[&Block]) -> Option<ImportMap> {
|
||||
let Some(package) = package else {
|
||||
return None;
|
||||
};
|
||||
let Some(module_path) = to_module_path(package, path) else {
|
||||
return None;
|
||||
};
|
||||
|
||||
let num_imports = blocks.iter().map(|block| block.imports.len()).sum();
|
||||
let mut module_imports = Vec::with_capacity(num_imports);
|
||||
for stmt in blocks.iter().flat_map(|block| &block.imports) {
|
||||
match &stmt.node {
|
||||
StmtKind::Import { names } => {
|
||||
module_imports.extend(names.iter().map(|name| {
|
||||
ModuleImport::new(
|
||||
name.node.name.clone(),
|
||||
stmt.location,
|
||||
stmt.end_location.unwrap(),
|
||||
)
|
||||
}));
|
||||
}
|
||||
StmtKind::ImportFrom {
|
||||
module,
|
||||
names,
|
||||
level,
|
||||
} => {
|
||||
let level = level.unwrap_or(0);
|
||||
let module = if let Some(module) = module {
|
||||
if level == 0 {
|
||||
Cow::Borrowed(module)
|
||||
} else {
|
||||
if module_path.len() <= level {
|
||||
continue;
|
||||
}
|
||||
let prefix = module_path[..module_path.len() - level].join(".");
|
||||
Cow::Owned(format!("{prefix}.{module}"))
|
||||
}
|
||||
} else {
|
||||
if module_path.len() <= level {
|
||||
continue;
|
||||
}
|
||||
Cow::Owned(module_path[..module_path.len() - level].join("."))
|
||||
};
|
||||
module_imports.extend(names.iter().map(|name| {
|
||||
ModuleImport::new(
|
||||
format!("{}.{}", module, name.node.name),
|
||||
name.location,
|
||||
name.end_location.unwrap(),
|
||||
)
|
||||
}));
|
||||
}
|
||||
_ => panic!("Expected StmtKind::Import | StmtKind::ImportFrom"),
|
||||
}
|
||||
}
|
||||
|
||||
let mut import_map = ImportMap::default();
|
||||
import_map.insert(module_path.join("."), module_imports);
|
||||
Some(import_map)
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn check_imports(
|
||||
python_ast: &Suite,
|
||||
@@ -87,7 +25,7 @@ pub fn check_imports(
|
||||
autofix: flags::Autofix,
|
||||
path: &Path,
|
||||
package: Option<&Path>,
|
||||
) -> (Vec<Diagnostic>, Option<ImportMap>) {
|
||||
) -> Vec<Diagnostic> {
|
||||
// Extract all imports from the AST.
|
||||
let tracker = {
|
||||
let mut tracker = ImportTracker::new(locator, directives, path);
|
||||
@@ -114,9 +52,5 @@ pub fn check_imports(
|
||||
&blocks, python_ast, locator, stylist, settings, autofix,
|
||||
));
|
||||
}
|
||||
|
||||
// Extract import map.
|
||||
let imports = extract_import_map(path, package, &blocks);
|
||||
|
||||
(diagnostics, imports)
|
||||
diagnostics
|
||||
}
|
||||
|
||||
@@ -356,7 +356,6 @@ pub fn code_to_rule(linter: Linter, code: &str) -> Option<Rule> {
|
||||
(Flake8Simplify, "223") => Rule::ExprAndFalse,
|
||||
(Flake8Simplify, "300") => Rule::YodaConditions,
|
||||
(Flake8Simplify, "401") => Rule::IfElseBlockInsteadOfDictGet,
|
||||
(Flake8Simplify, "910") => Rule::DictGetWithNoneDefault,
|
||||
|
||||
// pyupgrade
|
||||
(Pyupgrade, "001") => Rule::UselessMetaclassType,
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
use rustpython_parser::ast::{Expr, Stmt};
|
||||
|
||||
use ruff_python_semantic::analyze::visibility::{
|
||||
use ruff_python_ast::visibility::{
|
||||
class_visibility, function_visibility, method_visibility, Modifier, Visibility, VisibleScope,
|
||||
};
|
||||
use rustpython_parser::ast::{Expr, Stmt};
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum DefinitionKind<'a> {
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
use rustpython_parser::ast::{Constant, Expr, ExprKind, Stmt, StmtKind};
|
||||
|
||||
use ruff_python_semantic::analyze::visibility;
|
||||
use ruff_python_ast::visibility::{Modifier, VisibleScope};
|
||||
|
||||
use crate::docstrings::definition::{Definition, DefinitionKind, Documentable};
|
||||
|
||||
@@ -28,7 +28,7 @@ pub fn docstring_from(suite: &[Stmt]) -> Option<&Expr> {
|
||||
|
||||
/// Extract a `Definition` from the AST node defined by a `Stmt`.
|
||||
pub fn extract<'a>(
|
||||
scope: visibility::VisibleScope,
|
||||
scope: VisibleScope,
|
||||
stmt: &'a Stmt,
|
||||
body: &'a [Stmt],
|
||||
kind: Documentable,
|
||||
@@ -36,22 +36,22 @@ pub fn extract<'a>(
|
||||
let expr = docstring_from(body);
|
||||
match kind {
|
||||
Documentable::Function => match scope {
|
||||
visibility::VisibleScope {
|
||||
modifier: visibility::Modifier::Module,
|
||||
VisibleScope {
|
||||
modifier: Modifier::Module,
|
||||
..
|
||||
} => Definition {
|
||||
kind: DefinitionKind::Function(stmt),
|
||||
docstring: expr,
|
||||
},
|
||||
visibility::VisibleScope {
|
||||
modifier: visibility::Modifier::Class,
|
||||
VisibleScope {
|
||||
modifier: Modifier::Class,
|
||||
..
|
||||
} => Definition {
|
||||
kind: DefinitionKind::Method(stmt),
|
||||
docstring: expr,
|
||||
},
|
||||
visibility::VisibleScope {
|
||||
modifier: visibility::Modifier::Function,
|
||||
VisibleScope {
|
||||
modifier: Modifier::Function,
|
||||
..
|
||||
} => Definition {
|
||||
kind: DefinitionKind::NestedFunction(stmt),
|
||||
@@ -59,22 +59,22 @@ pub fn extract<'a>(
|
||||
},
|
||||
},
|
||||
Documentable::Class => match scope {
|
||||
visibility::VisibleScope {
|
||||
modifier: visibility::Modifier::Module,
|
||||
VisibleScope {
|
||||
modifier: Modifier::Module,
|
||||
..
|
||||
} => Definition {
|
||||
kind: DefinitionKind::Class(stmt),
|
||||
docstring: expr,
|
||||
},
|
||||
visibility::VisibleScope {
|
||||
modifier: visibility::Modifier::Class,
|
||||
VisibleScope {
|
||||
modifier: Modifier::Class,
|
||||
..
|
||||
} => Definition {
|
||||
kind: DefinitionKind::NestedClass(stmt),
|
||||
docstring: expr,
|
||||
},
|
||||
visibility::VisibleScope {
|
||||
modifier: visibility::Modifier::Function,
|
||||
VisibleScope {
|
||||
modifier: Modifier::Function,
|
||||
..
|
||||
} => Definition {
|
||||
kind: DefinitionKind::NestedClass(stmt),
|
||||
|
||||
@@ -9,7 +9,6 @@ use rustpython_parser::lexer::LexResult;
|
||||
use rustpython_parser::ParseError;
|
||||
|
||||
use ruff_diagnostics::Diagnostic;
|
||||
use ruff_python_ast::imports::ImportMap;
|
||||
use ruff_python_ast::source_code::{Indexer, Locator, Stylist};
|
||||
use ruff_python_stdlib::path::is_python_stub_file;
|
||||
|
||||
@@ -52,15 +51,6 @@ impl<T> LinterResult<T> {
|
||||
|
||||
pub type FixTable = FxHashMap<Rule, usize>;
|
||||
|
||||
pub struct FixerResult<'a> {
|
||||
/// The result returned by the linter, after applying any fixes.
|
||||
pub result: LinterResult<(Vec<Message>, Option<ImportMap>)>,
|
||||
/// The resulting source code, after applying any fixes.
|
||||
pub transformed: Cow<'a, str>,
|
||||
/// The number of fixes applied for each [`Rule`].
|
||||
pub fixed: FixTable,
|
||||
}
|
||||
|
||||
/// Generate `Diagnostic`s from the source code contents at the
|
||||
/// given `Path`.
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
@@ -76,10 +66,9 @@ pub fn check_path(
|
||||
settings: &Settings,
|
||||
noqa: flags::Noqa,
|
||||
autofix: flags::Autofix,
|
||||
) -> LinterResult<(Vec<Diagnostic>, Option<ImportMap>)> {
|
||||
) -> LinterResult<Vec<Diagnostic>> {
|
||||
// Aggregate all diagnostics.
|
||||
let mut diagnostics = vec![];
|
||||
let mut imports = None;
|
||||
let mut error = None;
|
||||
|
||||
// Collect doc lines. This requires a rare mix of tokens (for comments) and AST
|
||||
@@ -153,7 +142,7 @@ pub fn check_path(
|
||||
));
|
||||
}
|
||||
if use_imports {
|
||||
let (import_diagnostics, module_imports) = check_imports(
|
||||
diagnostics.extend(check_imports(
|
||||
&python_ast,
|
||||
locator,
|
||||
indexer,
|
||||
@@ -163,9 +152,7 @@ pub fn check_path(
|
||||
autofix,
|
||||
path,
|
||||
package,
|
||||
);
|
||||
imports = module_imports;
|
||||
diagnostics.extend(import_diagnostics);
|
||||
));
|
||||
}
|
||||
if use_doc_lines {
|
||||
doc_lines.extend(doc_lines_from_ast(&python_ast));
|
||||
@@ -253,7 +240,7 @@ pub fn check_path(
|
||||
}
|
||||
}
|
||||
|
||||
LinterResult::new((diagnostics, imports), error)
|
||||
LinterResult::new(diagnostics, error)
|
||||
}
|
||||
|
||||
const MAX_ITERATIONS: usize = 100;
|
||||
@@ -310,7 +297,7 @@ pub fn add_noqa_to_path(path: &Path, package: Option<&Path>, settings: &Settings
|
||||
// Add any missing `# noqa` pragmas.
|
||||
add_noqa(
|
||||
path,
|
||||
&diagnostics.0,
|
||||
&diagnostics,
|
||||
&contents,
|
||||
indexer.commented_lines(),
|
||||
&directives.noqa_line_for,
|
||||
@@ -327,7 +314,7 @@ pub fn lint_only(
|
||||
settings: &Settings,
|
||||
noqa: flags::Noqa,
|
||||
autofix: flags::Autofix,
|
||||
) -> LinterResult<(Vec<Message>, Option<ImportMap>)> {
|
||||
) -> LinterResult<Vec<Message>> {
|
||||
// Tokenize once.
|
||||
let tokens: Vec<LexResult> = ruff_rustpython::tokenize(contents);
|
||||
|
||||
@@ -361,23 +348,20 @@ pub fn lint_only(
|
||||
|
||||
// Convert from diagnostics to messages.
|
||||
let path_lossy = path.to_string_lossy();
|
||||
result.map(|(messages, imports)| {
|
||||
(
|
||||
messages
|
||||
.into_iter()
|
||||
.map(|diagnostic| {
|
||||
let source = if settings.show_source {
|
||||
Some(Source::from_diagnostic(&diagnostic, &locator))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let lineno = diagnostic.location.row();
|
||||
let noqa_row = *directives.noqa_line_for.get(&lineno).unwrap_or(&lineno);
|
||||
Message::from_diagnostic(diagnostic, path_lossy.to_string(), source, noqa_row)
|
||||
})
|
||||
.collect(),
|
||||
imports,
|
||||
)
|
||||
result.map(|diagnostics| {
|
||||
diagnostics
|
||||
.into_iter()
|
||||
.map(|diagnostic| {
|
||||
let source = if settings.show_source {
|
||||
Some(Source::from_diagnostic(&diagnostic, &locator))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let lineno = diagnostic.location.row();
|
||||
let noqa_row = *directives.noqa_line_for.get(&lineno).unwrap_or(&lineno);
|
||||
Message::from_diagnostic(diagnostic, path_lossy.to_string(), source, noqa_row)
|
||||
})
|
||||
.collect()
|
||||
})
|
||||
}
|
||||
|
||||
@@ -389,7 +373,7 @@ pub fn lint_fix<'a>(
|
||||
package: Option<&Path>,
|
||||
noqa: flags::Noqa,
|
||||
settings: &Settings,
|
||||
) -> Result<FixerResult<'a>> {
|
||||
) -> Result<(LinterResult<Vec<Message>>, Cow<'a, str>, FixTable)> {
|
||||
let mut transformed = Cow::Borrowed(contents);
|
||||
|
||||
// Track the number of fixed errors across iterations.
|
||||
@@ -464,7 +448,7 @@ This indicates a bug in `{}`. If you could open an issue at:
|
||||
}
|
||||
|
||||
// Apply autofix.
|
||||
if let Some((fixed_contents, applied)) = fix_file(&result.data.0, &locator) {
|
||||
if let Some((fixed_contents, applied)) = fix_file(&result.data, &locator) {
|
||||
if iterations < MAX_ITERATIONS {
|
||||
// Count the number of fixed errors.
|
||||
for (rule, count) in applied {
|
||||
@@ -504,33 +488,29 @@ This indicates a bug in `{}`. If you could open an issue at:
|
||||
|
||||
// Convert to messages.
|
||||
let path_lossy = path.to_string_lossy();
|
||||
return Ok(FixerResult {
|
||||
result: result.map(|(messages, imports)| {
|
||||
(
|
||||
messages
|
||||
.into_iter()
|
||||
.map(|diagnostic| {
|
||||
let source = if settings.show_source {
|
||||
Some(Source::from_diagnostic(&diagnostic, &locator))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let lineno = diagnostic.location.row();
|
||||
let noqa_row =
|
||||
*directives.noqa_line_for.get(&lineno).unwrap_or(&lineno);
|
||||
Message::from_diagnostic(
|
||||
diagnostic,
|
||||
path_lossy.to_string(),
|
||||
source,
|
||||
noqa_row,
|
||||
)
|
||||
})
|
||||
.collect(),
|
||||
imports,
|
||||
)
|
||||
return Ok((
|
||||
result.map(|diagnostics| {
|
||||
diagnostics
|
||||
.into_iter()
|
||||
.map(|diagnostic| {
|
||||
let source = if settings.show_source {
|
||||
Some(Source::from_diagnostic(&diagnostic, &locator))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let lineno = diagnostic.location.row();
|
||||
let noqa_row = *directives.noqa_line_for.get(&lineno).unwrap_or(&lineno);
|
||||
Message::from_diagnostic(
|
||||
diagnostic,
|
||||
path_lossy.to_string(),
|
||||
source,
|
||||
noqa_row,
|
||||
)
|
||||
})
|
||||
.collect()
|
||||
}),
|
||||
transformed,
|
||||
fixed,
|
||||
});
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -322,7 +322,6 @@ ruff_macros::register_rules!(
|
||||
rules::flake8_simplify::rules::ExprAndFalse,
|
||||
rules::flake8_simplify::rules::YodaConditions,
|
||||
rules::flake8_simplify::rules::IfElseBlockInsteadOfDictGet,
|
||||
rules::flake8_simplify::rules::DictGetWithNoneDefault,
|
||||
// pyupgrade
|
||||
rules::pyupgrade::rules::UselessMetaclassType,
|
||||
rules::pyupgrade::rules::TypeOfPrimitive,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use rustpython_parser::ast::{Arguments, Expr, Stmt, StmtKind};
|
||||
|
||||
use ruff_python_ast::cast;
|
||||
use ruff_python_semantic::analyze::visibility;
|
||||
use ruff_python_ast::visibility;
|
||||
|
||||
use crate::checkers::ast::Checker;
|
||||
use crate::docstrings::definition::{Definition, DefinitionKind};
|
||||
|
||||
@@ -4,10 +4,10 @@ use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Violation};
|
||||
use ruff_macros::{derive_message_formats, violation};
|
||||
use ruff_python_ast::helpers::ReturnStatementVisitor;
|
||||
use ruff_python_ast::types::Range;
|
||||
use ruff_python_ast::visibility::Visibility;
|
||||
use ruff_python_ast::visibility::{self};
|
||||
use ruff_python_ast::visitor::Visitor;
|
||||
use ruff_python_ast::{cast, helpers};
|
||||
use ruff_python_semantic::analyze::visibility;
|
||||
use ruff_python_semantic::analyze::visibility::Visibility;
|
||||
use ruff_python_stdlib::typing::SIMPLE_MAGIC_RETURN_TYPES;
|
||||
|
||||
use crate::checkers::ast::Checker;
|
||||
|
||||
@@ -3,8 +3,8 @@ use rustpython_parser::ast::{Expr, ExprKind, Stmt, StmtKind};
|
||||
use ruff_diagnostics::{Diagnostic, Violation};
|
||||
use ruff_macros::{derive_message_formats, violation};
|
||||
use ruff_python_ast::helpers::{find_keyword, is_const_true};
|
||||
use ruff_python_ast::logging;
|
||||
use ruff_python_ast::types::Range;
|
||||
use ruff_python_semantic::analyze::logging;
|
||||
|
||||
use crate::checkers::ast::Checker;
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ use rustpython_parser::ast::{Constant, Expr, ExprKind, Keyword, Stmt, StmtKind};
|
||||
use ruff_diagnostics::{Diagnostic, Violation};
|
||||
use ruff_macros::{derive_message_formats, violation};
|
||||
use ruff_python_ast::types::Range;
|
||||
use ruff_python_semantic::analyze::visibility::{is_abstract, is_overload};
|
||||
use ruff_python_ast::visibility::{is_abstract, is_overload};
|
||||
|
||||
use crate::checkers::ast::Checker;
|
||||
use crate::registry::Rule;
|
||||
|
||||
@@ -2,8 +2,8 @@ use rustpython_parser::ast::{Expr, ExprKind};
|
||||
|
||||
use ruff_diagnostics::{Diagnostic, Violation};
|
||||
use ruff_macros::{derive_message_formats, violation};
|
||||
use ruff_python_ast::scope::ScopeKind;
|
||||
use ruff_python_ast::types::Range;
|
||||
use ruff_python_semantic::scope::ScopeKind;
|
||||
|
||||
use crate::checkers::ast::Checker;
|
||||
|
||||
|
||||
@@ -13,17 +13,17 @@ pub struct ExceptWithEmptyTuple;
|
||||
impl Violation for ExceptWithEmptyTuple {
|
||||
#[derive_message_formats]
|
||||
fn message(&self) -> String {
|
||||
format!("Using `except ():` with an empty tuple does not catch anything; add exceptions to handle")
|
||||
format!("Using except (): with an empty tuple does not handle/catch anything. Add exceptions to handle.")
|
||||
}
|
||||
}
|
||||
|
||||
/// B029
|
||||
pub fn except_with_empty_tuple(checker: &mut Checker, excepthandler: &Excepthandler) {
|
||||
let ExcepthandlerKind::ExceptHandler { type_, .. } = &excepthandler.node;
|
||||
let Some(type_) = type_ else {
|
||||
if type_.is_none() {
|
||||
return;
|
||||
};
|
||||
let ExprKind::Tuple { elts, .. } = &type_.node else {
|
||||
}
|
||||
let ExprKind::Tuple { elts, .. } = &type_.as_ref().unwrap().node else {
|
||||
return;
|
||||
};
|
||||
if elts.is_empty() {
|
||||
|
||||
@@ -33,7 +33,7 @@ fn flatten_starred_iterables(expr: &Expr) -> Vec<&Expr> {
|
||||
ExprKind::Tuple { elts, .. } | ExprKind::List { elts, .. } => {
|
||||
exprs_to_process.append(&mut elts.iter().collect());
|
||||
}
|
||||
_ => flattened_exprs.push(value),
|
||||
_ => flattened_exprs.push(expr),
|
||||
},
|
||||
_ => flattened_exprs.push(expr),
|
||||
}
|
||||
@@ -48,17 +48,12 @@ pub fn except_with_non_exception_classes(checker: &mut Checker, excepthandler: &
|
||||
return;
|
||||
};
|
||||
for expr in flatten_starred_iterables(type_) {
|
||||
if !matches!(
|
||||
&expr.node,
|
||||
ExprKind::Subscript { .. }
|
||||
| ExprKind::Attribute { .. }
|
||||
| ExprKind::Name { .. }
|
||||
| ExprKind::Call { .. },
|
||||
) {
|
||||
checker.diagnostics.push(Diagnostic::new(
|
||||
match expr.node {
|
||||
ExprKind::Attribute { .. } | ExprKind::Name { .. } | ExprKind::Call { .. } => (),
|
||||
_ => checker.diagnostics.push(Diagnostic::new(
|
||||
ExceptWithNonExceptionClasses,
|
||||
Range::from(expr),
|
||||
));
|
||||
)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,24 +49,13 @@ struct GroupNameFinder<'a> {
|
||||
/// Variable name for the group.
|
||||
group_name: &'a str,
|
||||
/// Number of times the `group_name` variable was seen during the visit.
|
||||
usage_count: u32,
|
||||
usage_count: u8,
|
||||
/// A flag indicating that the visitor is inside a nested `for` or `while`
|
||||
/// loop or inside a `dict`, `list` or `set` comprehension.
|
||||
nested: bool,
|
||||
/// A flag indicating that the `group_name` variable has been overridden
|
||||
/// during the visit.
|
||||
overridden: bool,
|
||||
/// A stack of `if` statements.
|
||||
parent_ifs: Vec<&'a Stmt>,
|
||||
/// A stack of counters where each counter is itself a list of usage count.
|
||||
/// This is used specifically for mutually exclusive statements such as an
|
||||
/// `if` or `match`.
|
||||
///
|
||||
/// The stack element represents an entire `if` or `match` statement while
|
||||
/// the number inside the element represents the usage count for one of
|
||||
/// the branches of the statement. The order of the count corresponds the
|
||||
/// branch order.
|
||||
counter_stack: Vec<Vec<u32>>,
|
||||
/// A list of reused expressions.
|
||||
exprs: Vec<&'a Expr>,
|
||||
}
|
||||
@@ -78,8 +67,6 @@ impl<'a> GroupNameFinder<'a> {
|
||||
usage_count: 0,
|
||||
nested: false,
|
||||
overridden: false,
|
||||
parent_ifs: Vec::new(),
|
||||
counter_stack: Vec::new(),
|
||||
exprs: Vec::new(),
|
||||
}
|
||||
}
|
||||
@@ -132,78 +119,6 @@ where
|
||||
visitor::walk_body(self, body);
|
||||
self.nested = false;
|
||||
}
|
||||
StmtKind::If { test, body, orelse } => {
|
||||
// Determine whether we're on an `if` arm (as opposed to an `elif`).
|
||||
let is_if_arm = !self.parent_ifs.iter().any(|parent| {
|
||||
if let StmtKind::If { orelse, .. } = &parent.node {
|
||||
orelse.len() == 1 && &orelse[0] == stmt
|
||||
} else {
|
||||
false
|
||||
}
|
||||
});
|
||||
|
||||
if is_if_arm {
|
||||
// Initialize the vector with the count for current branch.
|
||||
self.counter_stack.push(vec![0]);
|
||||
} else {
|
||||
// SAFETY: `unwrap` is safe because we're either in `elif` or
|
||||
// `else` branch which can come only after an `if` branch.
|
||||
// When inside an `if` branch, a new vector will be pushed
|
||||
// onto the stack.
|
||||
self.counter_stack.last_mut().unwrap().push(0);
|
||||
}
|
||||
|
||||
let has_else = orelse
|
||||
.first()
|
||||
.map_or(false, |expr| !matches!(expr.node, StmtKind::If { .. }));
|
||||
|
||||
self.parent_ifs.push(stmt);
|
||||
if has_else {
|
||||
// There's no `StmtKind::Else`; instead, the `else` contents are directly on
|
||||
// the `orelse` of the `StmtKind::If` node. We want to add a new counter for
|
||||
// the `orelse` branch, but first, we need to visit the `if` body manually.
|
||||
self.visit_expr(test);
|
||||
self.visit_body(body);
|
||||
|
||||
// Now, we're in an `else` block.
|
||||
self.counter_stack.last_mut().unwrap().push(0);
|
||||
self.visit_body(orelse);
|
||||
} else {
|
||||
visitor::walk_stmt(self, stmt);
|
||||
}
|
||||
self.parent_ifs.pop();
|
||||
|
||||
if is_if_arm {
|
||||
if let Some(last) = self.counter_stack.pop() {
|
||||
// This is the max number of group usage from all the
|
||||
// branches of this `if` statement.
|
||||
let max_count = last.into_iter().max().unwrap_or(0);
|
||||
if let Some(current_last) = self.counter_stack.last_mut() {
|
||||
*current_last.last_mut().unwrap() += max_count;
|
||||
} else {
|
||||
self.usage_count += max_count;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
StmtKind::Match { subject, cases } => {
|
||||
self.counter_stack.push(Vec::with_capacity(cases.len()));
|
||||
self.visit_expr(subject);
|
||||
for match_case in cases {
|
||||
self.counter_stack.last_mut().unwrap().push(0);
|
||||
self.visit_match_case(match_case);
|
||||
}
|
||||
if let Some(last) = self.counter_stack.pop() {
|
||||
// This is the max number of group usage from all the
|
||||
// branches of this `match` statement.
|
||||
let max_count = last.into_iter().max().unwrap_or(0);
|
||||
if let Some(current_last) = self.counter_stack.last_mut() {
|
||||
*current_last.last_mut().unwrap() += max_count;
|
||||
} else {
|
||||
self.usage_count += max_count;
|
||||
}
|
||||
}
|
||||
}
|
||||
StmtKind::Assign { targets, .. } => {
|
||||
if targets.iter().any(|target| self.name_matches(target)) {
|
||||
self.overridden = true;
|
||||
@@ -235,25 +150,10 @@ where
|
||||
visitor::walk_expr(self, expr);
|
||||
self.nested = false;
|
||||
} else if self.name_matches(expr) {
|
||||
// If the stack isn't empty, then we're in one of the branches of
|
||||
// a mutually exclusive statement. Otherwise, we'll add it to the
|
||||
// global count.
|
||||
if let Some(last) = self.counter_stack.last_mut() {
|
||||
*last.last_mut().unwrap() += 1;
|
||||
} else {
|
||||
self.usage_count += 1;
|
||||
}
|
||||
|
||||
let current_usage_count = self.usage_count
|
||||
+ self
|
||||
.counter_stack
|
||||
.iter()
|
||||
.map(|count| count.last().unwrap_or(&0))
|
||||
.sum::<u32>();
|
||||
|
||||
self.usage_count += 1;
|
||||
// For nested loops, the variable usage could be once but the
|
||||
// loop makes it being used multiple times.
|
||||
if self.nested || current_usage_count > 1 {
|
||||
if self.nested || self.usage_count > 1 {
|
||||
self.exprs.push(expr);
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -140,9 +140,7 @@ pub fn unused_loop_control_variable(
|
||||
}
|
||||
|
||||
// Avoid fixing any variables that _may_ be used, but undetectably so.
|
||||
let certainty = Certainty::from(!helpers::uses_magic_variable_access(body, |id| {
|
||||
checker.ctx.is_builtin(id)
|
||||
}));
|
||||
let certainty = Certainty::from(!helpers::uses_magic_variable_access(&checker.ctx, body));
|
||||
|
||||
// Attempt to rename the variable by prepending an underscore, but avoid
|
||||
// applying the fix if doing so wouldn't actually cause us to ignore the
|
||||
@@ -166,13 +164,17 @@ pub fn unused_loop_control_variable(
|
||||
if certainty.into() && checker.patch(diagnostic.kind.rule()) {
|
||||
// Find the `BindingKind::LoopVar` corresponding to the name.
|
||||
let scope = checker.ctx.scope();
|
||||
let binding = scope.bindings_for_name(name).find_map(|index| {
|
||||
let binding = &checker.ctx.bindings[*index];
|
||||
binding
|
||||
.source
|
||||
.as_ref()
|
||||
.and_then(|source| (source == &RefEquality(stmt)).then_some(binding))
|
||||
});
|
||||
let binding = scope
|
||||
.get(name)
|
||||
.into_iter()
|
||||
.chain(scope.rebounds.get(name).into_iter().flatten())
|
||||
.find_map(|index| {
|
||||
let binding = &checker.ctx.bindings[*index];
|
||||
binding
|
||||
.source
|
||||
.as_ref()
|
||||
.and_then(|source| (source == &RefEquality(stmt)).then_some(binding))
|
||||
});
|
||||
if let Some(binding) = binding {
|
||||
if binding.kind.is_loop_var() {
|
||||
if !binding.used() {
|
||||
|
||||
@@ -54,7 +54,7 @@ pub fn useless_expression(checker: &mut Checker, value: &Expr) {
|
||||
}
|
||||
|
||||
// Ignore statements that have side effects.
|
||||
if contains_effect(value, |id| checker.ctx.is_builtin(id)) {
|
||||
if contains_effect(&checker.ctx, value) {
|
||||
// Flag attributes as useless expressions, even if they're attached to calls or other
|
||||
// expressions.
|
||||
if matches!(value.node, ExprKind::Attribute { .. }) {
|
||||
|
||||
@@ -4,7 +4,7 @@ expression: diagnostics
|
||||
---
|
||||
- kind:
|
||||
name: ExceptWithEmptyTuple
|
||||
body: "Using `except ():` with an empty tuple does not catch anything; add exceptions to handle"
|
||||
body: "Using except (): with an empty tuple does not handle/catch anything. Add exceptions to handle."
|
||||
suggestion: ~
|
||||
fixable: false
|
||||
location:
|
||||
@@ -18,7 +18,7 @@ expression: diagnostics
|
||||
parent: ~
|
||||
- kind:
|
||||
name: ExceptWithEmptyTuple
|
||||
body: "Using `except ():` with an empty tuple does not catch anything; add exceptions to handle"
|
||||
body: "Using except (): with an empty tuple does not handle/catch anything. Add exceptions to handle."
|
||||
suggestion: ~
|
||||
fixable: false
|
||||
location:
|
||||
|
||||
@@ -58,18 +58,4 @@ expression: diagnostics
|
||||
fix:
|
||||
edits: []
|
||||
parent: ~
|
||||
- kind:
|
||||
name: ExceptWithNonExceptionClasses
|
||||
body: "`except` handlers should only be exception classes or tuples of exception classes"
|
||||
suggestion: ~
|
||||
fixable: false
|
||||
location:
|
||||
row: 33
|
||||
column: 28
|
||||
end_location:
|
||||
row: 33
|
||||
column: 49
|
||||
fix:
|
||||
edits: []
|
||||
parent: ~
|
||||
|
||||
|
||||
@@ -100,158 +100,4 @@ expression: diagnostics
|
||||
fix:
|
||||
edits: []
|
||||
parent: ~
|
||||
- kind:
|
||||
name: ReuseOfGroupbyGenerator
|
||||
body: "Using the generator returned from `itertools.groupby()` more than once will do nothing on the second usage"
|
||||
suggestion: ~
|
||||
fixable: false
|
||||
location:
|
||||
row: 86
|
||||
column: 36
|
||||
end_location:
|
||||
row: 86
|
||||
column: 49
|
||||
fix:
|
||||
edits: []
|
||||
parent: ~
|
||||
- kind:
|
||||
name: ReuseOfGroupbyGenerator
|
||||
body: "Using the generator returned from `itertools.groupby()` more than once will do nothing on the second usage"
|
||||
suggestion: ~
|
||||
fixable: false
|
||||
location:
|
||||
row: 93
|
||||
column: 40
|
||||
end_location:
|
||||
row: 93
|
||||
column: 53
|
||||
fix:
|
||||
edits: []
|
||||
parent: ~
|
||||
- kind:
|
||||
name: ReuseOfGroupbyGenerator
|
||||
body: "Using the generator returned from `itertools.groupby()` more than once will do nothing on the second usage"
|
||||
suggestion: ~
|
||||
fixable: false
|
||||
location:
|
||||
row: 95
|
||||
column: 40
|
||||
end_location:
|
||||
row: 95
|
||||
column: 53
|
||||
fix:
|
||||
edits: []
|
||||
parent: ~
|
||||
- kind:
|
||||
name: ReuseOfGroupbyGenerator
|
||||
body: "Using the generator returned from `itertools.groupby()` more than once will do nothing on the second usage"
|
||||
suggestion: ~
|
||||
fixable: false
|
||||
location:
|
||||
row: 97
|
||||
column: 40
|
||||
end_location:
|
||||
row: 97
|
||||
column: 53
|
||||
fix:
|
||||
edits: []
|
||||
parent: ~
|
||||
- kind:
|
||||
name: ReuseOfGroupbyGenerator
|
||||
body: "Using the generator returned from `itertools.groupby()` more than once will do nothing on the second usage"
|
||||
suggestion: ~
|
||||
fixable: false
|
||||
location:
|
||||
row: 98
|
||||
column: 36
|
||||
end_location:
|
||||
row: 98
|
||||
column: 49
|
||||
fix:
|
||||
edits: []
|
||||
parent: ~
|
||||
- kind:
|
||||
name: ReuseOfGroupbyGenerator
|
||||
body: "Using the generator returned from `itertools.groupby()` more than once will do nothing on the second usage"
|
||||
suggestion: ~
|
||||
fixable: false
|
||||
location:
|
||||
row: 105
|
||||
column: 48
|
||||
end_location:
|
||||
row: 105
|
||||
column: 61
|
||||
fix:
|
||||
edits: []
|
||||
parent: ~
|
||||
- kind:
|
||||
name: ReuseOfGroupbyGenerator
|
||||
body: "Using the generator returned from `itertools.groupby()` more than once will do nothing on the second usage"
|
||||
suggestion: ~
|
||||
fixable: false
|
||||
location:
|
||||
row: 111
|
||||
column: 32
|
||||
end_location:
|
||||
row: 111
|
||||
column: 45
|
||||
fix:
|
||||
edits: []
|
||||
parent: ~
|
||||
- kind:
|
||||
name: ReuseOfGroupbyGenerator
|
||||
body: "Using the generator returned from `itertools.groupby()` more than once will do nothing on the second usage"
|
||||
suggestion: ~
|
||||
fixable: false
|
||||
location:
|
||||
row: 120
|
||||
column: 48
|
||||
end_location:
|
||||
row: 120
|
||||
column: 61
|
||||
fix:
|
||||
edits: []
|
||||
parent: ~
|
||||
- kind:
|
||||
name: ReuseOfGroupbyGenerator
|
||||
body: "Using the generator returned from `itertools.groupby()` more than once will do nothing on the second usage"
|
||||
suggestion: ~
|
||||
fixable: false
|
||||
location:
|
||||
row: 122
|
||||
column: 48
|
||||
end_location:
|
||||
row: 122
|
||||
column: 61
|
||||
fix:
|
||||
edits: []
|
||||
parent: ~
|
||||
- kind:
|
||||
name: ReuseOfGroupbyGenerator
|
||||
body: "Using the generator returned from `itertools.groupby()` more than once will do nothing on the second usage"
|
||||
suggestion: ~
|
||||
fixable: false
|
||||
location:
|
||||
row: 125
|
||||
column: 40
|
||||
end_location:
|
||||
row: 125
|
||||
column: 53
|
||||
fix:
|
||||
edits: []
|
||||
parent: ~
|
||||
- kind:
|
||||
name: ReuseOfGroupbyGenerator
|
||||
body: "Using the generator returned from `itertools.groupby()` more than once will do nothing on the second usage"
|
||||
suggestion: ~
|
||||
fixable: false
|
||||
location:
|
||||
row: 129
|
||||
column: 32
|
||||
end_location:
|
||||
row: 129
|
||||
column: 45
|
||||
fix:
|
||||
edits: []
|
||||
parent: ~
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use rustpython_parser::ast::Expr;
|
||||
|
||||
use ruff_python_semantic::context::Context;
|
||||
use ruff_python_ast::context::Context;
|
||||
|
||||
/// Return `true` if a Python class appears to be a Django model, based on its base classes.
|
||||
pub fn is_model(context: &Context, base: &Expr) -> bool {
|
||||
|
||||
@@ -2,9 +2,8 @@ use rustpython_parser::ast::{Constant, Expr, ExprKind, Keyword, Location, Operat
|
||||
|
||||
use ruff_diagnostics::{Diagnostic, Edit};
|
||||
use ruff_python_ast::helpers::{find_keyword, SimpleCallArgs};
|
||||
use ruff_python_ast::logging;
|
||||
use ruff_python_ast::types::Range;
|
||||
use ruff_python_semantic::analyze::logging;
|
||||
use ruff_python_stdlib::logging::LoggingLevel;
|
||||
|
||||
use crate::checkers::ast::Checker;
|
||||
use crate::registry::{AsRule, Rule};
|
||||
@@ -129,7 +128,7 @@ fn check_log_record_attr_clash(checker: &mut Checker, extra: &Keyword) {
|
||||
#[derive(Copy, Clone)]
|
||||
enum LoggingCallType {
|
||||
/// Logging call with a level method, e.g., `logging.info`.
|
||||
LevelCall(LoggingLevel),
|
||||
LevelCall(logging::LoggingLevel),
|
||||
/// Logging call with an integer level as an argument, e.g., `logger.log(level, ...)`.
|
||||
LogCall,
|
||||
}
|
||||
@@ -139,7 +138,7 @@ impl LoggingCallType {
|
||||
if attr == "log" {
|
||||
Some(LoggingCallType::LogCall)
|
||||
} else {
|
||||
LoggingLevel::from_attribute(attr).map(LoggingCallType::LevelCall)
|
||||
logging::LoggingLevel::from_attribute(attr).map(LoggingCallType::LevelCall)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -174,7 +173,7 @@ pub fn logging_call(checker: &mut Checker, func: &Expr, args: &[Expr], keywords:
|
||||
if checker.settings.rules.enabled(Rule::LoggingWarn)
|
||||
&& matches!(
|
||||
logging_call_type,
|
||||
LoggingCallType::LevelCall(LoggingLevel::Warn)
|
||||
LoggingCallType::LevelCall(logging::LoggingLevel::Warn)
|
||||
)
|
||||
{
|
||||
let mut diagnostic = Diagnostic::new(LoggingWarn, level_call_range);
|
||||
@@ -229,14 +228,14 @@ pub fn logging_call(checker: &mut Checker, func: &Expr, args: &[Expr], keywords:
|
||||
|
||||
if let LoggingCallType::LevelCall(logging_level) = logging_call_type {
|
||||
match logging_level {
|
||||
LoggingLevel::Error => {
|
||||
logging::LoggingLevel::Error => {
|
||||
if checker.settings.rules.enabled(Rule::LoggingExcInfo) {
|
||||
checker
|
||||
.diagnostics
|
||||
.push(Diagnostic::new(LoggingExcInfo, level_call_range));
|
||||
}
|
||||
}
|
||||
LoggingLevel::Exception => {
|
||||
logging::LoggingLevel::Exception => {
|
||||
if checker
|
||||
.settings
|
||||
.rules
|
||||
|
||||
@@ -8,19 +8,19 @@ expression: diagnostics
|
||||
suggestion: "Convert to `warn`"
|
||||
fixable: true
|
||||
location:
|
||||
row: 4
|
||||
row: 3
|
||||
column: 8
|
||||
end_location:
|
||||
row: 4
|
||||
row: 3
|
||||
column: 12
|
||||
fix:
|
||||
edits:
|
||||
- content: warning
|
||||
location:
|
||||
row: 4
|
||||
row: 3
|
||||
column: 8
|
||||
end_location:
|
||||
row: 4
|
||||
row: 3
|
||||
column: 12
|
||||
parent: ~
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ use ruff_python_ast::helpers::{any_over_expr, create_expr, match_trailing_commen
|
||||
use ruff_python_ast::types::{Range, RefEquality};
|
||||
use ruff_python_stdlib::identifiers::is_identifier;
|
||||
|
||||
use crate::autofix::actions::delete_stmt;
|
||||
use crate::autofix::helpers::delete_stmt;
|
||||
use crate::checkers::ast::Checker;
|
||||
use crate::message::Location;
|
||||
use crate::registry::AsRule;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use crate::autofix::actions::delete_stmt;
|
||||
use crate::autofix::helpers::delete_stmt;
|
||||
use log::error;
|
||||
use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic};
|
||||
use ruff_macros::{derive_message_formats, violation};
|
||||
|
||||
@@ -221,23 +221,6 @@ fn is_valid_default_value_with_annotation(
|
||||
false
|
||||
}
|
||||
|
||||
pub fn is_type_var_call(checker: &Checker, expr: &Expr) -> bool {
|
||||
let ExprKind::Call {func, ..} = &expr.node else {
|
||||
return false;
|
||||
};
|
||||
checker
|
||||
.ctx
|
||||
.resolve_call_path(func)
|
||||
.map_or(false, |call_path| {
|
||||
call_path.as_slice() == ["typing", "TypeVar"]
|
||||
|| call_path.as_slice() == ["typing", "TypeVarTuple"]
|
||||
|| call_path.as_slice() == ["typing_extensions", "TypeVarTuple"]
|
||||
|| call_path.as_slice() == ["typing", "NewType"]
|
||||
|| call_path.as_slice() == ["typing", "ParamSpec"]
|
||||
|| call_path.as_slice() == ["typing_extensions", "ParamSpec"]
|
||||
})
|
||||
}
|
||||
|
||||
/// PYI011
|
||||
pub fn typed_argument_simple_defaults(checker: &mut Checker, args: &Arguments) {
|
||||
if !args.defaults.is_empty() {
|
||||
@@ -359,9 +342,6 @@ pub fn assignment_default_in_stub(checker: &mut Checker, value: &Expr, annotatio
|
||||
}) {
|
||||
return;
|
||||
}
|
||||
if is_type_var_call(checker, value) {
|
||||
return;
|
||||
}
|
||||
if !is_valid_default_value_with_annotation(value, checker, true) {
|
||||
let mut diagnostic = Diagnostic::new(AssignmentDefaultInStub, Range::from(value));
|
||||
|
||||
|
||||
@@ -8,19 +8,19 @@ expression: diagnostics
|
||||
suggestion: "Replace default value with `...`"
|
||||
fixable: true
|
||||
location:
|
||||
row: 44
|
||||
row: 40
|
||||
column: 22
|
||||
end_location:
|
||||
row: 44
|
||||
row: 40
|
||||
column: 57
|
||||
fix:
|
||||
edits:
|
||||
- content: "..."
|
||||
location:
|
||||
row: 44
|
||||
row: 40
|
||||
column: 22
|
||||
end_location:
|
||||
row: 44
|
||||
row: 40
|
||||
column: 57
|
||||
parent: ~
|
||||
- kind:
|
||||
@@ -29,19 +29,19 @@ expression: diagnostics
|
||||
suggestion: "Replace default value with `...`"
|
||||
fixable: true
|
||||
location:
|
||||
row: 45
|
||||
row: 41
|
||||
column: 22
|
||||
end_location:
|
||||
row: 45
|
||||
row: 41
|
||||
column: 34
|
||||
fix:
|
||||
edits:
|
||||
- content: "..."
|
||||
location:
|
||||
row: 45
|
||||
row: 41
|
||||
column: 22
|
||||
end_location:
|
||||
row: 45
|
||||
row: 41
|
||||
column: 34
|
||||
parent: ~
|
||||
- kind:
|
||||
@@ -50,19 +50,19 @@ expression: diagnostics
|
||||
suggestion: "Replace default value with `...`"
|
||||
fixable: true
|
||||
location:
|
||||
row: 46
|
||||
row: 42
|
||||
column: 22
|
||||
end_location:
|
||||
row: 46
|
||||
row: 42
|
||||
column: 37
|
||||
fix:
|
||||
edits:
|
||||
- content: "..."
|
||||
location:
|
||||
row: 46
|
||||
row: 42
|
||||
column: 22
|
||||
end_location:
|
||||
row: 46
|
||||
row: 42
|
||||
column: 37
|
||||
parent: ~
|
||||
- kind:
|
||||
@@ -71,19 +71,19 @@ expression: diagnostics
|
||||
suggestion: "Replace default value with `...`"
|
||||
fixable: true
|
||||
location:
|
||||
row: 47
|
||||
row: 43
|
||||
column: 25
|
||||
end_location:
|
||||
row: 47
|
||||
row: 43
|
||||
column: 35
|
||||
fix:
|
||||
edits:
|
||||
- content: "..."
|
||||
location:
|
||||
row: 47
|
||||
row: 43
|
||||
column: 25
|
||||
end_location:
|
||||
row: 47
|
||||
row: 43
|
||||
column: 35
|
||||
parent: ~
|
||||
- kind:
|
||||
@@ -92,19 +92,19 @@ expression: diagnostics
|
||||
suggestion: "Replace default value with `...`"
|
||||
fixable: true
|
||||
location:
|
||||
row: 48
|
||||
row: 44
|
||||
column: 46
|
||||
end_location:
|
||||
row: 48
|
||||
row: 44
|
||||
column: 69
|
||||
fix:
|
||||
edits:
|
||||
- content: "..."
|
||||
location:
|
||||
row: 48
|
||||
row: 44
|
||||
column: 46
|
||||
end_location:
|
||||
row: 48
|
||||
row: 44
|
||||
column: 69
|
||||
parent: ~
|
||||
- kind:
|
||||
@@ -113,19 +113,19 @@ expression: diagnostics
|
||||
suggestion: "Replace default value with `...`"
|
||||
fixable: true
|
||||
location:
|
||||
row: 49
|
||||
row: 45
|
||||
column: 30
|
||||
end_location:
|
||||
row: 49
|
||||
row: 45
|
||||
column: 53
|
||||
fix:
|
||||
edits:
|
||||
- content: "..."
|
||||
location:
|
||||
row: 49
|
||||
row: 45
|
||||
column: 30
|
||||
end_location:
|
||||
row: 49
|
||||
row: 45
|
||||
column: 53
|
||||
parent: ~
|
||||
- kind:
|
||||
@@ -134,19 +134,19 @@ expression: diagnostics
|
||||
suggestion: "Replace default value with `...`"
|
||||
fixable: true
|
||||
location:
|
||||
row: 50
|
||||
row: 46
|
||||
column: 36
|
||||
end_location:
|
||||
row: 50
|
||||
row: 46
|
||||
column: 47
|
||||
fix:
|
||||
edits:
|
||||
- content: "..."
|
||||
location:
|
||||
row: 50
|
||||
row: 46
|
||||
column: 36
|
||||
end_location:
|
||||
row: 50
|
||||
row: 46
|
||||
column: 47
|
||||
parent: ~
|
||||
- kind:
|
||||
@@ -155,19 +155,19 @@ expression: diagnostics
|
||||
suggestion: "Replace default value with `...`"
|
||||
fixable: true
|
||||
location:
|
||||
row: 52
|
||||
row: 48
|
||||
column: 27
|
||||
end_location:
|
||||
row: 52
|
||||
row: 48
|
||||
column: 43
|
||||
fix:
|
||||
edits:
|
||||
- content: "..."
|
||||
location:
|
||||
row: 52
|
||||
row: 48
|
||||
column: 27
|
||||
end_location:
|
||||
row: 52
|
||||
row: 48
|
||||
column: 43
|
||||
parent: ~
|
||||
- kind:
|
||||
@@ -176,19 +176,19 @@ expression: diagnostics
|
||||
suggestion: "Replace default value with `...`"
|
||||
fixable: true
|
||||
location:
|
||||
row: 53
|
||||
row: 49
|
||||
column: 10
|
||||
end_location:
|
||||
row: 53
|
||||
row: 49
|
||||
column: 23
|
||||
fix:
|
||||
edits:
|
||||
- content: "..."
|
||||
location:
|
||||
row: 53
|
||||
row: 49
|
||||
column: 10
|
||||
end_location:
|
||||
row: 53
|
||||
row: 49
|
||||
column: 23
|
||||
parent: ~
|
||||
- kind:
|
||||
@@ -197,19 +197,19 @@ expression: diagnostics
|
||||
suggestion: "Replace default value with `...`"
|
||||
fixable: true
|
||||
location:
|
||||
row: 54
|
||||
row: 50
|
||||
column: 10
|
||||
end_location:
|
||||
row: 54
|
||||
row: 50
|
||||
column: 25
|
||||
fix:
|
||||
edits:
|
||||
- content: "..."
|
||||
location:
|
||||
row: 54
|
||||
row: 50
|
||||
column: 10
|
||||
end_location:
|
||||
row: 54
|
||||
row: 50
|
||||
column: 25
|
||||
parent: ~
|
||||
- kind:
|
||||
@@ -218,19 +218,19 @@ expression: diagnostics
|
||||
suggestion: "Replace default value with `...`"
|
||||
fixable: true
|
||||
location:
|
||||
row: 55
|
||||
row: 51
|
||||
column: 10
|
||||
end_location:
|
||||
row: 55
|
||||
row: 51
|
||||
column: 15
|
||||
fix:
|
||||
edits:
|
||||
- content: "..."
|
||||
location:
|
||||
row: 55
|
||||
row: 51
|
||||
column: 10
|
||||
end_location:
|
||||
row: 55
|
||||
row: 51
|
||||
column: 15
|
||||
parent: ~
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ use ruff_python_ast::types::Range;
|
||||
use ruff_python_ast::visitor;
|
||||
use ruff_python_ast::visitor::Visitor;
|
||||
|
||||
use crate::autofix::actions::remove_argument;
|
||||
use crate::autofix::helpers::remove_argument;
|
||||
use crate::checkers::ast::Checker;
|
||||
use crate::registry::{AsRule, Rule};
|
||||
|
||||
|
||||
@@ -3,8 +3,8 @@ use rustpython_parser::ast::{Expr, ExprKind};
|
||||
use ruff_diagnostics::{Diagnostic, Violation};
|
||||
use ruff_macros::{derive_message_formats, violation};
|
||||
use ruff_python_ast::call_path::collect_call_path;
|
||||
use ruff_python_ast::scope::ScopeKind;
|
||||
use ruff_python_ast::types::Range;
|
||||
use ruff_python_semantic::scope::ScopeKind;
|
||||
|
||||
use crate::checkers::ast::Checker;
|
||||
|
||||
|
||||
@@ -38,7 +38,6 @@ mod tests {
|
||||
#[test_case(Rule::ExprAndFalse, Path::new("SIM223.py"); "SIM223")]
|
||||
#[test_case(Rule::YodaConditions, Path::new("SIM300.py"); "SIM300")]
|
||||
#[test_case(Rule::IfElseBlockInsteadOfDictGet, Path::new("SIM401.py"); "SIM401")]
|
||||
#[test_case(Rule::DictGetWithNoneDefault, Path::new("SIM910.py"); "SIM910")]
|
||||
#[test_case(Rule::IfElseBlockInsteadOfDictLookup, Path::new("SIM116.py"); "SIM116")]
|
||||
#[test_case(Rule::IfWithSameArms, Path::new("SIM114.py"); "SIM114")]
|
||||
fn rules(rule_code: Rule, path: &Path) -> Result<()> {
|
||||
|
||||
@@ -11,9 +11,9 @@ use rustpython_parser::ast::{
|
||||
use ruff_diagnostics::{AlwaysAutofixableViolation, AutofixKind, Diagnostic, Edit, Violation};
|
||||
use ruff_macros::{derive_message_formats, violation};
|
||||
use ruff_python_ast::comparable::ComparableExpr;
|
||||
use ruff_python_ast::context::Context;
|
||||
use ruff_python_ast::helpers::{contains_effect, create_expr, has_comments, unparse_expr};
|
||||
use ruff_python_ast::types::Range;
|
||||
use ruff_python_semantic::context::Context;
|
||||
|
||||
use crate::checkers::ast::Checker;
|
||||
use crate::registry::AsRule;
|
||||
@@ -213,7 +213,7 @@ pub fn duplicate_isinstance_call(checker: &mut Checker, expr: &Expr) {
|
||||
} else {
|
||||
unreachable!("Indices should only contain `isinstance` calls")
|
||||
};
|
||||
let fixable = !contains_effect(target, |id| checker.ctx.is_builtin(id));
|
||||
let fixable = !contains_effect(&checker.ctx, target);
|
||||
let mut diagnostic = Diagnostic::new(
|
||||
DuplicateIsinstanceCall {
|
||||
name: if let ExprKind::Name { id, .. } = &target.node {
|
||||
@@ -341,7 +341,7 @@ pub fn compare_with_tuple(checker: &mut Checker, expr: &Expr) {
|
||||
// Avoid rewriting (e.g.) `a == "foo" or a == f()`.
|
||||
if comparators
|
||||
.iter()
|
||||
.any(|expr| contains_effect(expr, |id| checker.ctx.is_builtin(id)))
|
||||
.any(|expr| contains_effect(&checker.ctx, expr))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
@@ -423,7 +423,7 @@ pub fn expr_and_not_expr(checker: &mut Checker, expr: &Expr) {
|
||||
return;
|
||||
}
|
||||
|
||||
if contains_effect(expr, |id| checker.ctx.is_builtin(id)) {
|
||||
if contains_effect(&checker.ctx, expr) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -477,7 +477,7 @@ pub fn expr_or_not_expr(checker: &mut Checker, expr: &Expr) {
|
||||
return;
|
||||
}
|
||||
|
||||
if contains_effect(expr, |id| checker.ctx.is_builtin(id)) {
|
||||
if contains_effect(&checker.ctx, expr) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -522,7 +522,7 @@ pub fn is_short_circuit(
|
||||
let mut location = expr.location;
|
||||
for (value, next_value) in values.iter().tuple_windows() {
|
||||
// Keep track of the location of the furthest-right, non-effectful expression.
|
||||
if contains_effect(value, |id| ctx.is_builtin(id)) {
|
||||
if contains_effect(ctx, value) {
|
||||
location = next_value.location;
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -27,25 +27,6 @@ impl AlwaysAutofixableViolation for UncapitalizedEnvironmentVariables {
|
||||
}
|
||||
}
|
||||
|
||||
#[violation]
|
||||
pub struct DictGetWithNoneDefault {
|
||||
pub expected: String,
|
||||
pub original: String,
|
||||
}
|
||||
|
||||
impl AlwaysAutofixableViolation for DictGetWithNoneDefault {
|
||||
#[derive_message_formats]
|
||||
fn message(&self) -> String {
|
||||
let DictGetWithNoneDefault { expected, original } = self;
|
||||
format!("Use `{expected}` instead of `{original}`")
|
||||
}
|
||||
|
||||
fn autofix_title(&self) -> String {
|
||||
let DictGetWithNoneDefault { expected, original } = self;
|
||||
format!("Replace `{original}` with `{expected}`")
|
||||
}
|
||||
}
|
||||
|
||||
/// SIM112
|
||||
pub fn use_capital_environment_variables(checker: &mut Checker, expr: &Expr) {
|
||||
// check `os.environ['foo']`
|
||||
@@ -142,64 +123,3 @@ fn check_os_environ_subscript(checker: &mut Checker, expr: &Expr) {
|
||||
}
|
||||
checker.diagnostics.push(diagnostic);
|
||||
}
|
||||
|
||||
/// SIM910
|
||||
pub fn dict_get_with_none_default(checker: &mut Checker, expr: &Expr) {
|
||||
let ExprKind::Call { func, args, keywords } = &expr.node else {
|
||||
return;
|
||||
};
|
||||
if !keywords.is_empty() {
|
||||
return;
|
||||
}
|
||||
let ExprKind::Attribute { value, attr, .. } = &func.node else {
|
||||
return;
|
||||
};
|
||||
if !matches!(value.node, ExprKind::Dict { .. }) {
|
||||
return;
|
||||
}
|
||||
if attr != "get" {
|
||||
return;
|
||||
}
|
||||
let Some(key) = args.get(0) else {
|
||||
return;
|
||||
};
|
||||
if !matches!(key.node, ExprKind::Constant { .. } | ExprKind::Name { .. }) {
|
||||
return;
|
||||
}
|
||||
let Some(default) = args.get(1) else {
|
||||
return;
|
||||
};
|
||||
if !matches!(
|
||||
default.node,
|
||||
ExprKind::Constant {
|
||||
value: Constant::None,
|
||||
..
|
||||
}
|
||||
) {
|
||||
return;
|
||||
};
|
||||
|
||||
let expected = format!(
|
||||
"{}({})",
|
||||
checker.locator.slice(func),
|
||||
checker.locator.slice(key)
|
||||
);
|
||||
let original = checker.locator.slice(expr).to_string();
|
||||
|
||||
let mut diagnostic = Diagnostic::new(
|
||||
DictGetWithNoneDefault {
|
||||
expected: expected.clone(),
|
||||
original,
|
||||
},
|
||||
Range::from(expr),
|
||||
);
|
||||
|
||||
if checker.patch(diagnostic.kind.rule()) {
|
||||
diagnostic.set_fix(Edit::replacement(
|
||||
expected,
|
||||
expr.location,
|
||||
expr.end_location.unwrap(),
|
||||
));
|
||||
}
|
||||
checker.diagnostics.push(diagnostic);
|
||||
}
|
||||
|
||||
@@ -7,12 +7,11 @@ use ruff_diagnostics::{AutofixKind, Diagnostic, Edit, Violation};
|
||||
use ruff_macros::{derive_message_formats, violation};
|
||||
use ruff_python_ast::comparable::{ComparableConstant, ComparableExpr, ComparableStmt};
|
||||
use ruff_python_ast::helpers::{
|
||||
any_over_expr, contains_effect, create_expr, create_stmt, first_colon_range, has_comments,
|
||||
contains_call_path, contains_effect, create_expr, create_stmt, first_colon_range, has_comments,
|
||||
has_comments_in, unparse_expr, unparse_stmt,
|
||||
};
|
||||
use ruff_python_ast::newlines::StrExt;
|
||||
use ruff_python_ast::types::Range;
|
||||
use ruff_python_semantic::context::Context;
|
||||
|
||||
use crate::checkers::ast::Checker;
|
||||
use crate::registry::AsRule;
|
||||
@@ -416,14 +415,6 @@ fn ternary(target_var: &Expr, body_value: &Expr, test: &Expr, orelse_value: &Exp
|
||||
})
|
||||
}
|
||||
|
||||
/// Return `true` if the `Expr` contains a reference to `${module}.${target}`.
|
||||
fn contains_call_path(ctx: &Context, expr: &Expr, target: &[&str]) -> bool {
|
||||
any_over_expr(expr, &|expr| {
|
||||
ctx.resolve_call_path(expr)
|
||||
.map_or(false, |call_path| call_path.as_slice() == target)
|
||||
})
|
||||
}
|
||||
|
||||
/// SIM108
|
||||
pub fn use_ternary_operator(checker: &mut Checker, stmt: &Stmt, parent: Option<&Stmt>) {
|
||||
let StmtKind::If { test, body, orelse } = &stmt.node else {
|
||||
@@ -648,9 +639,10 @@ pub fn manual_dict_lookup(
|
||||
let StmtKind::Return { value, .. } = &body[0].node else {
|
||||
return;
|
||||
};
|
||||
if value.as_ref().map_or(false, |value| {
|
||||
contains_effect(value, |id| checker.ctx.is_builtin(id))
|
||||
}) {
|
||||
if value
|
||||
.as_ref()
|
||||
.map_or(false, |value| contains_effect(&checker.ctx, value))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -720,9 +712,10 @@ pub fn manual_dict_lookup(
|
||||
let StmtKind::Return { value, .. } = &body[0].node else {
|
||||
return;
|
||||
};
|
||||
if value.as_ref().map_or(false, |value| {
|
||||
contains_effect(value, |id| checker.ctx.is_builtin(id))
|
||||
}) {
|
||||
if value
|
||||
.as_ref()
|
||||
.map_or(false, |value| contains_effect(&checker.ctx, value))
|
||||
{
|
||||
return;
|
||||
};
|
||||
|
||||
@@ -764,13 +757,13 @@ pub fn use_dict_get_with_default(
|
||||
if body.len() != 1 || orelse.len() != 1 {
|
||||
return;
|
||||
}
|
||||
let StmtKind::Assign { targets: body_var, value: body_value, ..} = &body[0].node else {
|
||||
let StmtKind::Assign { targets: body_var, value: body_val, ..} = &body[0].node else {
|
||||
return;
|
||||
};
|
||||
if body_var.len() != 1 {
|
||||
return;
|
||||
};
|
||||
let StmtKind::Assign { targets: orelse_var, value: orelse_value, .. } = &orelse[0].node else {
|
||||
let StmtKind::Assign { targets: orelse_var, value: orelse_val, .. } = &orelse[0].node else {
|
||||
return;
|
||||
};
|
||||
if orelse_var.len() != 1 {
|
||||
@@ -782,15 +775,15 @@ pub fn use_dict_get_with_default(
|
||||
if test_dict.len() != 1 {
|
||||
return;
|
||||
}
|
||||
let (expected_var, expected_value, default_var, default_value) = match ops[..] {
|
||||
[Cmpop::In] => (&body_var[0], body_value, &orelse_var[0], orelse_value),
|
||||
[Cmpop::NotIn] => (&orelse_var[0], orelse_value, &body_var[0], body_value),
|
||||
let (expected_var, expected_val, default_var, default_val) = match ops[..] {
|
||||
[Cmpop::In] => (&body_var[0], body_val, &orelse_var[0], orelse_val),
|
||||
[Cmpop::NotIn] => (&orelse_var[0], orelse_val, &body_var[0], body_val),
|
||||
_ => {
|
||||
return;
|
||||
}
|
||||
};
|
||||
let test_dict = &test_dict[0];
|
||||
let ExprKind::Subscript { value: expected_subscript, slice: expected_slice, .. } = &expected_value.node else {
|
||||
let ExprKind::Subscript { value: expected_subscript, slice: expected_slice, .. } = &expected_val.node else {
|
||||
return;
|
||||
};
|
||||
|
||||
@@ -804,7 +797,7 @@ pub fn use_dict_get_with_default(
|
||||
}
|
||||
|
||||
// Check that the default value is not "complex".
|
||||
if contains_effect(default_value, |id| checker.ctx.is_builtin(id)) {
|
||||
if contains_effect(&checker.ctx, default_val) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -849,7 +842,7 @@ pub fn use_dict_get_with_default(
|
||||
})),
|
||||
args: vec![
|
||||
create_expr(test_key.node.clone()),
|
||||
create_expr(default_value.node.clone()),
|
||||
create_expr(default_val.node.clone()),
|
||||
],
|
||||
keywords: vec![],
|
||||
})),
|
||||
|
||||
@@ -3,8 +3,8 @@ use rustpython_parser::ast::{Cmpop, Expr, ExprKind, Stmt, StmtKind, Unaryop};
|
||||
use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Edit};
|
||||
use ruff_macros::{derive_message_formats, violation};
|
||||
use ruff_python_ast::helpers::{create_expr, unparse_expr};
|
||||
use ruff_python_ast::scope::ScopeKind;
|
||||
use ruff_python_ast::types::Range;
|
||||
use ruff_python_semantic::scope::ScopeKind;
|
||||
|
||||
use crate::checkers::ast::Checker;
|
||||
use crate::registry::AsRule;
|
||||
|
||||
@@ -3,10 +3,7 @@ pub use ast_bool_op::{
|
||||
expr_or_not_expr, expr_or_true, CompareWithTuple, DuplicateIsinstanceCall, ExprAndFalse,
|
||||
ExprAndNotExpr, ExprOrNotExpr, ExprOrTrue,
|
||||
};
|
||||
pub use ast_expr::{
|
||||
dict_get_with_none_default, use_capital_environment_variables, DictGetWithNoneDefault,
|
||||
UncapitalizedEnvironmentVariables,
|
||||
};
|
||||
pub use ast_expr::{use_capital_environment_variables, UncapitalizedEnvironmentVariables};
|
||||
pub use ast_if::{
|
||||
if_with_same_arms, manual_dict_lookup, needless_bool, nested_if_statements,
|
||||
use_dict_get_with_default, use_ternary_operator, CollapsibleIf, IfElseBlockInsteadOfDictGet,
|
||||
|
||||
@@ -86,88 +86,4 @@ expression: diagnostics
|
||||
row: 10
|
||||
column: 15
|
||||
parent: ~
|
||||
- kind:
|
||||
name: UncapitalizedEnvironmentVariables
|
||||
body: "Use capitalized environment variable `FOO` instead of `foo`"
|
||||
suggestion: "Replace `foo` with `FOO`"
|
||||
fixable: true
|
||||
location:
|
||||
row: 12
|
||||
column: 21
|
||||
end_location:
|
||||
row: 12
|
||||
column: 26
|
||||
fix:
|
||||
edits:
|
||||
- content: "'FOO'"
|
||||
location:
|
||||
row: 12
|
||||
column: 21
|
||||
end_location:
|
||||
row: 12
|
||||
column: 26
|
||||
parent: ~
|
||||
- kind:
|
||||
name: UncapitalizedEnvironmentVariables
|
||||
body: "Use capitalized environment variable `FOO` instead of `foo`"
|
||||
suggestion: "Replace `foo` with `FOO`"
|
||||
fixable: true
|
||||
location:
|
||||
row: 14
|
||||
column: 17
|
||||
end_location:
|
||||
row: 14
|
||||
column: 22
|
||||
fix:
|
||||
edits:
|
||||
- content: "'FOO'"
|
||||
location:
|
||||
row: 14
|
||||
column: 17
|
||||
end_location:
|
||||
row: 14
|
||||
column: 22
|
||||
parent: ~
|
||||
- kind:
|
||||
name: UncapitalizedEnvironmentVariables
|
||||
body: "Use capitalized environment variable `FOO` instead of `foo`"
|
||||
suggestion: "Replace `foo` with `FOO`"
|
||||
fixable: true
|
||||
location:
|
||||
row: 16
|
||||
column: 25
|
||||
end_location:
|
||||
row: 16
|
||||
column: 30
|
||||
fix:
|
||||
edits:
|
||||
- content: "'FOO'"
|
||||
location:
|
||||
row: 16
|
||||
column: 25
|
||||
end_location:
|
||||
row: 16
|
||||
column: 30
|
||||
parent: ~
|
||||
- kind:
|
||||
name: UncapitalizedEnvironmentVariables
|
||||
body: "Use capitalized environment variable `FOO` instead of `foo`"
|
||||
suggestion: "Replace `foo` with `FOO`"
|
||||
fixable: true
|
||||
location:
|
||||
row: 19
|
||||
column: 21
|
||||
end_location:
|
||||
row: 19
|
||||
column: 26
|
||||
fix:
|
||||
edits:
|
||||
- content: "'FOO'"
|
||||
location:
|
||||
row: 19
|
||||
column: 21
|
||||
end_location:
|
||||
row: 19
|
||||
column: 26
|
||||
parent: ~
|
||||
|
||||
|
||||
@@ -1,110 +0,0 @@
|
||||
---
|
||||
source: crates/ruff/src/rules/flake8_simplify/mod.rs
|
||||
expression: diagnostics
|
||||
---
|
||||
- kind:
|
||||
name: DictGetWithNoneDefault
|
||||
body: "Use `{}.get(key)` instead of `{}.get(key, None)`"
|
||||
suggestion: "Replace `{}.get(key, None)` with `{}.get(key)`"
|
||||
fixable: true
|
||||
location:
|
||||
row: 2
|
||||
column: 0
|
||||
end_location:
|
||||
row: 2
|
||||
column: 17
|
||||
fix:
|
||||
edits:
|
||||
- content: "{}.get(key)"
|
||||
location:
|
||||
row: 2
|
||||
column: 0
|
||||
end_location:
|
||||
row: 2
|
||||
column: 17
|
||||
parent: ~
|
||||
- kind:
|
||||
name: DictGetWithNoneDefault
|
||||
body: "Use `{}.get(\"key\")` instead of `{}.get(\"key\", None)`"
|
||||
suggestion: "Replace `{}.get(\"key\", None)` with `{}.get(\"key\")`"
|
||||
fixable: true
|
||||
location:
|
||||
row: 5
|
||||
column: 0
|
||||
end_location:
|
||||
row: 5
|
||||
column: 19
|
||||
fix:
|
||||
edits:
|
||||
- content: "{}.get(\"key\")"
|
||||
location:
|
||||
row: 5
|
||||
column: 0
|
||||
end_location:
|
||||
row: 5
|
||||
column: 19
|
||||
parent: ~
|
||||
- kind:
|
||||
name: DictGetWithNoneDefault
|
||||
body: "Use `{}.get(key)` instead of `{}.get(key, None)`"
|
||||
suggestion: "Replace `{}.get(key, None)` with `{}.get(key)`"
|
||||
fixable: true
|
||||
location:
|
||||
row: 20
|
||||
column: 8
|
||||
end_location:
|
||||
row: 20
|
||||
column: 25
|
||||
fix:
|
||||
edits:
|
||||
- content: "{}.get(key)"
|
||||
location:
|
||||
row: 20
|
||||
column: 8
|
||||
end_location:
|
||||
row: 20
|
||||
column: 25
|
||||
parent: ~
|
||||
- kind:
|
||||
name: DictGetWithNoneDefault
|
||||
body: "Use `{}.get(key)` instead of `{}.get(key, None)`"
|
||||
suggestion: "Replace `{}.get(key, None)` with `{}.get(key)`"
|
||||
fixable: true
|
||||
location:
|
||||
row: 24
|
||||
column: 4
|
||||
end_location:
|
||||
row: 24
|
||||
column: 21
|
||||
fix:
|
||||
edits:
|
||||
- content: "{}.get(key)"
|
||||
location:
|
||||
row: 24
|
||||
column: 4
|
||||
end_location:
|
||||
row: 24
|
||||
column: 21
|
||||
parent: ~
|
||||
- kind:
|
||||
name: DictGetWithNoneDefault
|
||||
body: "Use `({}).get(key)` instead of `({}).get(key, None)`"
|
||||
suggestion: "Replace `({}).get(key, None)` with `({}).get(key)`"
|
||||
fixable: true
|
||||
location:
|
||||
row: 27
|
||||
column: 0
|
||||
end_location:
|
||||
row: 27
|
||||
column: 19
|
||||
fix:
|
||||
edits:
|
||||
- content: "({}).get(key)"
|
||||
location:
|
||||
row: 27
|
||||
column: 0
|
||||
end_location:
|
||||
row: 27
|
||||
column: 19
|
||||
parent: ~
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
use num_traits::Zero;
|
||||
use rustpython_parser::ast::{Constant, Expr, ExprKind};
|
||||
|
||||
use ruff_python_ast::binding::{Binding, BindingKind, ExecutionContext};
|
||||
use ruff_python_ast::call_path::from_qualified_name;
|
||||
use ruff_python_ast::context::Context;
|
||||
use ruff_python_ast::helpers::map_callable;
|
||||
use ruff_python_semantic::binding::{Binding, BindingKind, ExecutionContext};
|
||||
use ruff_python_semantic::context::Context;
|
||||
use ruff_python_semantic::scope::ScopeKind;
|
||||
use ruff_python_ast::scope::ScopeKind;
|
||||
|
||||
/// Return `true` if [`Expr`] is a guard for a type-checking block.
|
||||
pub fn is_type_checking_block(context: &Context, test: &Expr) -> bool {
|
||||
|
||||
@@ -5,7 +5,7 @@ use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic};
|
||||
use ruff_macros::{derive_message_formats, violation};
|
||||
use ruff_python_ast::types::{Range, RefEquality};
|
||||
|
||||
use crate::autofix::actions::delete_stmt;
|
||||
use crate::autofix::helpers::delete_stmt;
|
||||
use crate::checkers::ast::Checker;
|
||||
use crate::registry::AsRule;
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use ruff_diagnostics::{Diagnostic, Violation};
|
||||
use ruff_macros::{derive_message_formats, violation};
|
||||
use ruff_python_semantic::binding::{
|
||||
use ruff_python_ast::binding::{
|
||||
Binding, BindingKind, ExecutionContext, FromImportation, Importation, SubmoduleImportation,
|
||||
};
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@ use std::path::Path;
|
||||
|
||||
use ruff_diagnostics::{Diagnostic, Violation};
|
||||
use ruff_macros::{derive_message_formats, violation};
|
||||
use ruff_python_semantic::binding::{
|
||||
use ruff_python_ast::binding::{
|
||||
Binding, BindingKind, ExecutionContext, FromImportation, Importation, SubmoduleImportation,
|
||||
};
|
||||
|
||||
|
||||
@@ -5,11 +5,11 @@ use rustpython_parser::ast::{Arg, Arguments};
|
||||
|
||||
use ruff_diagnostics::{Diagnostic, Violation};
|
||||
use ruff_macros::{derive_message_formats, violation};
|
||||
use ruff_python_semantic::analyze::function_type;
|
||||
use ruff_python_semantic::analyze::function_type::FunctionType;
|
||||
use ruff_python_semantic::analyze::visibility;
|
||||
use ruff_python_semantic::binding::Bindings;
|
||||
use ruff_python_semantic::scope::{FunctionDef, Lambda, Scope, ScopeKind};
|
||||
use ruff_python_ast::binding::Bindings;
|
||||
use ruff_python_ast::function_type;
|
||||
use ruff_python_ast::function_type::FunctionType;
|
||||
use ruff_python_ast::scope::{FunctionDef, Lambda, Scope, ScopeKind};
|
||||
use ruff_python_ast::visibility;
|
||||
|
||||
use crate::checkers::ast::Checker;
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ use rustpython_parser::ast::{Expr, ExprKind, Keyword, Location};
|
||||
use ruff_diagnostics::{Edit, Fix};
|
||||
use ruff_python_ast::source_code::Locator;
|
||||
|
||||
use crate::autofix::actions::remove_argument;
|
||||
use crate::autofix::helpers::remove_argument;
|
||||
|
||||
fn match_name(expr: &Expr) -> Option<&str> {
|
||||
if let ExprKind::Call { func, .. } = &expr.node {
|
||||
|
||||
@@ -31,8 +31,7 @@ mod tests {
|
||||
let directives =
|
||||
directives::extract_directives(&tokens, directives::Flags::from_settings(&settings));
|
||||
let LinterResult {
|
||||
data: (diagnostics, _imports),
|
||||
..
|
||||
data: diagnostics, ..
|
||||
} = check_path(
|
||||
Path::new("<filename>"),
|
||||
None,
|
||||
|
||||
@@ -3,8 +3,8 @@ use rustpython_parser::ast::{Expr, ExprKind};
|
||||
use ruff_diagnostics::Violation;
|
||||
use ruff_diagnostics::{Diagnostic, DiagnosticKind};
|
||||
use ruff_macros::{derive_message_formats, violation};
|
||||
use ruff_python_ast::binding::BindingKind;
|
||||
use ruff_python_ast::types::Range;
|
||||
use ruff_python_semantic::binding::BindingKind;
|
||||
|
||||
use crate::checkers::ast::Checker;
|
||||
use crate::registry::Rule;
|
||||
|
||||
@@ -3,8 +3,8 @@ use rustpython_parser::ast::{Expr, ExprKind};
|
||||
use ruff_diagnostics::Violation;
|
||||
use ruff_diagnostics::{Diagnostic, DiagnosticKind};
|
||||
use ruff_macros::{derive_message_formats, violation};
|
||||
use ruff_python_ast::binding::{BindingKind, Importation};
|
||||
use ruff_python_ast::types::Range;
|
||||
use ruff_python_semantic::binding::{BindingKind, Importation};
|
||||
|
||||
use crate::checkers::ast::Checker;
|
||||
use crate::registry::Rule;
|
||||
|
||||
@@ -3,8 +3,8 @@ use rustpython_parser::ast::Stmt;
|
||||
use ruff_diagnostics::{Diagnostic, Violation};
|
||||
use ruff_macros::{derive_message_formats, violation};
|
||||
use ruff_python_ast::helpers::identifier_range;
|
||||
use ruff_python_ast::scope::{Scope, ScopeKind};
|
||||
use ruff_python_ast::source_code::Locator;
|
||||
use ruff_python_semantic::scope::{Scope, ScopeKind};
|
||||
|
||||
/// ## What it does
|
||||
/// Checks for functions with "dunder" names (that is, names with two
|
||||
|
||||
@@ -2,9 +2,9 @@ use rustpython_parser::ast::{Arguments, Expr};
|
||||
|
||||
use ruff_diagnostics::{Diagnostic, Violation};
|
||||
use ruff_macros::{derive_message_formats, violation};
|
||||
use ruff_python_ast::function_type;
|
||||
use ruff_python_ast::scope::Scope;
|
||||
use ruff_python_ast::types::Range;
|
||||
use ruff_python_semantic::analyze::function_type;
|
||||
use ruff_python_semantic::scope::Scope;
|
||||
|
||||
use crate::checkers::ast::Checker;
|
||||
|
||||
|
||||
@@ -2,9 +2,9 @@ use rustpython_parser::ast::{Arguments, Expr};
|
||||
|
||||
use ruff_diagnostics::{Diagnostic, Violation};
|
||||
use ruff_macros::{derive_message_formats, violation};
|
||||
use ruff_python_ast::function_type;
|
||||
use ruff_python_ast::scope::Scope;
|
||||
use ruff_python_ast::types::Range;
|
||||
use ruff_python_semantic::analyze::function_type;
|
||||
use ruff_python_semantic::scope::Scope;
|
||||
|
||||
use crate::checkers::ast::Checker;
|
||||
|
||||
|
||||
@@ -4,10 +4,10 @@ use ruff_diagnostics::{AutofixKind, Diagnostic, Edit, Violation};
|
||||
use ruff_macros::{derive_message_formats, violation};
|
||||
use ruff_python_ast::helpers::{match_leading_content, match_trailing_content, unparse_stmt};
|
||||
use ruff_python_ast::newlines::StrExt;
|
||||
use ruff_python_ast::scope::ScopeKind;
|
||||
use ruff_python_ast::source_code::Stylist;
|
||||
use ruff_python_ast::types::Range;
|
||||
use ruff_python_ast::whitespace::leading_space;
|
||||
use ruff_python_semantic::scope::ScopeKind;
|
||||
|
||||
use crate::checkers::ast::Checker;
|
||||
use crate::registry::AsRule;
|
||||
|
||||
@@ -60,9 +60,6 @@ mod tests {
|
||||
#[test_case(Rule::UndocumentedPublicMethod, Path::new("D.py"); "D102_0")]
|
||||
#[test_case(Rule::UndocumentedPublicMethod, Path::new("setter.py"); "D102_1")]
|
||||
#[test_case(Rule::UndocumentedPublicModule, Path::new("D.py"); "D100")]
|
||||
#[test_case(Rule::UndocumentedPublicModule, Path::new("_unrelated/pkg/D100_pub.py"); "D100_ignore_unrelated_pub")]
|
||||
#[test_case(Rule::UndocumentedPublicModule, Path::new("_unrelated/pkg/_priv/no_D100_priv.py"); "no_d100_priv")]
|
||||
#[test_case(Rule::UndocumentedPublicModule, Path::new("_unrelated/_no_pkg_priv.py"); "no_d100_priv_script")]
|
||||
#[test_case(Rule::UndocumentedPublicNestedClass, Path::new("D.py"); "D106")]
|
||||
#[test_case(Rule::UndocumentedPublicPackage, Path::new("D.py"); "D104_0")]
|
||||
#[test_case(Rule::UndocumentedPublicPackage, Path::new("D104/__init__.py"); "D104_1")]
|
||||
|
||||
@@ -2,7 +2,7 @@ use ruff_diagnostics::{Diagnostic, Violation};
|
||||
use ruff_macros::{derive_message_formats, violation};
|
||||
use ruff_python_ast::cast;
|
||||
use ruff_python_ast::helpers::identifier_range;
|
||||
use ruff_python_semantic::analyze::visibility::is_overload;
|
||||
use ruff_python_ast::visibility::is_overload;
|
||||
|
||||
use crate::checkers::ast::Checker;
|
||||
use crate::docstrings::definition::{DefinitionKind, Docstring};
|
||||
|
||||
@@ -9,7 +9,7 @@ use ruff_python_ast::call_path::{from_qualified_name, CallPath};
|
||||
use ruff_python_ast::cast;
|
||||
use ruff_python_ast::newlines::StrExt;
|
||||
use ruff_python_ast::types::Range;
|
||||
use ruff_python_semantic::analyze::visibility::{is_property, is_test};
|
||||
use ruff_python_ast::visibility::{is_property, is_test};
|
||||
|
||||
use crate::checkers::ast::Checker;
|
||||
use crate::docstrings::definition::{DefinitionKind, Docstring};
|
||||
|
||||
@@ -3,7 +3,7 @@ use ruff_macros::{derive_message_formats, violation};
|
||||
use ruff_python_ast::cast;
|
||||
use ruff_python_ast::helpers::identifier_range;
|
||||
use ruff_python_ast::types::Range;
|
||||
use ruff_python_semantic::analyze::visibility::{
|
||||
use ruff_python_ast::visibility::{
|
||||
is_call, is_init, is_magic, is_new, is_overload, is_override, Visibility,
|
||||
};
|
||||
|
||||
|
||||
@@ -10,8 +10,8 @@ use ruff_macros::{derive_message_formats, violation};
|
||||
use ruff_python_ast::helpers::identifier_range;
|
||||
use ruff_python_ast::newlines::NewlineWithTrailingNewline;
|
||||
use ruff_python_ast::types::Range;
|
||||
use ruff_python_ast::visibility::is_staticmethod;
|
||||
use ruff_python_ast::{cast, whitespace};
|
||||
use ruff_python_semantic::analyze::visibility::is_staticmethod;
|
||||
|
||||
use crate::checkers::ast::Checker;
|
||||
use crate::docstrings::definition::{DefinitionKind, Docstring};
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
---
|
||||
source: crates/ruff/src/rules/pydocstyle/mod.rs
|
||||
expression: diagnostics
|
||||
---
|
||||
[]
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
---
|
||||
source: crates/ruff/src/rules/pydocstyle/mod.rs
|
||||
expression: diagnostics
|
||||
---
|
||||
- kind:
|
||||
name: UndocumentedPublicModule
|
||||
body: Missing docstring in public module
|
||||
suggestion: ~
|
||||
fixable: false
|
||||
location:
|
||||
row: 1
|
||||
column: 0
|
||||
end_location:
|
||||
row: 1
|
||||
column: 0
|
||||
fix:
|
||||
edits: []
|
||||
parent: ~
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
---
|
||||
source: crates/ruff/src/rules/pydocstyle/mod.rs
|
||||
expression: diagnostics
|
||||
---
|
||||
[]
|
||||
|
||||
@@ -23,7 +23,7 @@ pub(crate) fn error_to_string(err: &FormatParseError) -> String {
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct FormatSummary {
|
||||
pub autos: Vec<usize>,
|
||||
pub indices: Vec<usize>,
|
||||
pub indexes: Vec<usize>,
|
||||
pub keywords: Vec<String>,
|
||||
pub has_nested_parts: bool,
|
||||
pub format_string: FormatString,
|
||||
@@ -36,7 +36,7 @@ impl TryFrom<&str> for FormatSummary {
|
||||
let format_string = FormatString::from_str(literal)?;
|
||||
|
||||
let mut autos = Vec::new();
|
||||
let mut indices = Vec::new();
|
||||
let mut indexes = Vec::new();
|
||||
let mut keywords = Vec::new();
|
||||
let mut has_nested_parts = false;
|
||||
|
||||
@@ -51,7 +51,7 @@ impl TryFrom<&str> for FormatSummary {
|
||||
let parsed = FieldName::parse(field_name)?;
|
||||
match parsed.field_type {
|
||||
FieldType::Auto => autos.push(autos.len()),
|
||||
FieldType::Index(i) => indices.push(i),
|
||||
FieldType::Index(i) => indexes.push(i),
|
||||
FieldType::Keyword(k) => keywords.push(k),
|
||||
};
|
||||
|
||||
@@ -63,7 +63,7 @@ impl TryFrom<&str> for FormatSummary {
|
||||
let parsed = FieldName::parse(&field_name)?;
|
||||
match parsed.field_type {
|
||||
FieldType::Auto => autos.push(autos.len()),
|
||||
FieldType::Index(i) => indices.push(i),
|
||||
FieldType::Index(i) => indexes.push(i),
|
||||
FieldType::Keyword(k) => keywords.push(k),
|
||||
};
|
||||
has_nested_parts = true;
|
||||
@@ -72,7 +72,7 @@ impl TryFrom<&str> for FormatSummary {
|
||||
|
||||
Ok(FormatSummary {
|
||||
autos,
|
||||
indices,
|
||||
indexes,
|
||||
keywords,
|
||||
has_nested_parts,
|
||||
format_string,
|
||||
@@ -89,7 +89,7 @@ mod tests {
|
||||
let literal = "foo{foo}a{}b{2}c{2}d{1}{}{}e{bar}{foo}f{spam}";
|
||||
|
||||
let expected_autos = [0usize, 1usize, 2usize].to_vec();
|
||||
let expected_indices = [2usize, 2usize, 1usize].to_vec();
|
||||
let expected_indexes = [2usize, 2usize, 1usize].to_vec();
|
||||
let expected_keywords: Vec<_> = ["foo", "bar", "foo", "spam"]
|
||||
.into_iter()
|
||||
.map(String::from)
|
||||
@@ -98,7 +98,7 @@ mod tests {
|
||||
let format_summary = FormatSummary::try_from(literal).unwrap();
|
||||
|
||||
assert_eq!(format_summary.autos, expected_autos);
|
||||
assert_eq!(format_summary.indices, expected_indices);
|
||||
assert_eq!(format_summary.indexes, expected_indexes);
|
||||
assert_eq!(format_summary.keywords, expected_keywords);
|
||||
assert!(!format_summary.has_nested_parts);
|
||||
}
|
||||
@@ -108,7 +108,7 @@ mod tests {
|
||||
let literal = "foo{foo}a{:{}{}}b{2:{3}{4}}c{2}d{1}{}e{bar:{spam}{eggs}}";
|
||||
|
||||
let expected_autos = [0usize, 1usize, 2usize, 3usize].to_vec();
|
||||
let expected_indices = [2usize, 3usize, 4usize, 2usize, 1usize].to_vec();
|
||||
let expected_indexes = [2usize, 3usize, 4usize, 2usize, 1usize].to_vec();
|
||||
let expected_keywords: Vec<_> = ["foo", "bar", "spam", "eggs"]
|
||||
.into_iter()
|
||||
.map(String::from)
|
||||
@@ -117,7 +117,7 @@ mod tests {
|
||||
let format_summary = FormatSummary::try_from(literal).unwrap();
|
||||
|
||||
assert_eq!(format_summary.autos, expected_autos);
|
||||
assert_eq!(format_summary.indices, expected_indices);
|
||||
assert_eq!(format_summary.indexes, expected_indexes);
|
||||
assert_eq!(format_summary.keywords, expected_keywords);
|
||||
assert!(format_summary.has_nested_parts);
|
||||
}
|
||||
|
||||
@@ -258,7 +258,7 @@ mod tests {
|
||||
let directives =
|
||||
directives::extract_directives(&tokens, directives::Flags::from_settings(&settings));
|
||||
let LinterResult {
|
||||
data: (mut diagnostics, _imports),
|
||||
data: mut diagnostics,
|
||||
..
|
||||
} = check_path(
|
||||
Path::new("<filename>"),
|
||||
|
||||
@@ -2,8 +2,8 @@ use rustpython_parser::ast::Stmt;
|
||||
|
||||
use ruff_diagnostics::{Diagnostic, Violation};
|
||||
use ruff_macros::{derive_message_formats, violation};
|
||||
use ruff_python_ast::scope::ScopeKind;
|
||||
use ruff_python_ast::types::Range;
|
||||
use ruff_python_semantic::scope::ScopeKind;
|
||||
|
||||
use crate::checkers::ast::Checker;
|
||||
|
||||
|
||||
@@ -498,7 +498,7 @@ pub(crate) fn string_dot_format_extra_positional_arguments(
|
||||
}
|
||||
|
||||
let missing: Vec<usize> = (0..args.len())
|
||||
.filter(|i| !(summary.autos.contains(i) || summary.indices.contains(i)))
|
||||
.filter(|i| !(summary.autos.contains(i) || summary.indexes.contains(i)))
|
||||
.collect();
|
||||
|
||||
if missing.is_empty() {
|
||||
@@ -551,7 +551,7 @@ pub(crate) fn string_dot_format_missing_argument(
|
||||
let missing: Vec<String> = summary
|
||||
.autos
|
||||
.iter()
|
||||
.chain(summary.indices.iter())
|
||||
.chain(summary.indexes.iter())
|
||||
.filter(|&&i| i >= args.len())
|
||||
.map(ToString::to_string)
|
||||
.chain(
|
||||
@@ -577,7 +577,7 @@ pub(crate) fn string_dot_format_mixing_automatic(
|
||||
summary: &FormatSummary,
|
||||
location: Range,
|
||||
) {
|
||||
if !(summary.autos.is_empty() || summary.indices.is_empty()) {
|
||||
if !(summary.autos.is_empty() || summary.indexes.is_empty()) {
|
||||
checker
|
||||
.diagnostics
|
||||
.push(Diagnostic::new(StringDotFormatMixingAutomatic, location));
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use ruff_diagnostics::{Diagnostic, Violation};
|
||||
use ruff_macros::{derive_message_formats, violation};
|
||||
use ruff_python_ast::scope::Scope;
|
||||
use ruff_python_ast::types::Range;
|
||||
use ruff_python_semantic::scope::Scope;
|
||||
|
||||
#[violation]
|
||||
pub struct UndefinedExport {
|
||||
|
||||
@@ -2,8 +2,8 @@ use std::string::ToString;
|
||||
|
||||
use ruff_diagnostics::{Diagnostic, Violation};
|
||||
use ruff_macros::{derive_message_formats, violation};
|
||||
use ruff_python_semantic::binding::Bindings;
|
||||
use ruff_python_semantic::scope::{Scope, ScopeKind};
|
||||
use ruff_python_ast::binding::Bindings;
|
||||
use ruff_python_ast::scope::{Scope, ScopeKind};
|
||||
|
||||
#[violation]
|
||||
pub struct UndefinedLocal {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use ruff_diagnostics::{Diagnostic, Violation};
|
||||
use ruff_macros::{derive_message_formats, violation};
|
||||
use ruff_python_semantic::scope::ScopeId;
|
||||
use ruff_python_ast::scope::ScopeId;
|
||||
|
||||
use crate::checkers::ast::Checker;
|
||||
|
||||
|
||||
@@ -6,11 +6,11 @@ use rustpython_parser::{lexer, Mode, Tok};
|
||||
use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Edit};
|
||||
use ruff_macros::{derive_message_formats, violation};
|
||||
use ruff_python_ast::helpers::contains_effect;
|
||||
use ruff_python_ast::scope::{ScopeId, ScopeKind};
|
||||
use ruff_python_ast::source_code::Locator;
|
||||
use ruff_python_ast::types::{Range, RefEquality};
|
||||
use ruff_python_semantic::scope::{ScopeId, ScopeKind};
|
||||
|
||||
use crate::autofix::actions::delete_stmt;
|
||||
use crate::autofix::helpers::delete_stmt;
|
||||
use crate::checkers::ast::Checker;
|
||||
use crate::registry::AsRule;
|
||||
|
||||
@@ -202,9 +202,7 @@ fn remove_unused_variable(
|
||||
range.location == target.location && range.end_location == target.end_location.unwrap()
|
||||
}) {
|
||||
if matches!(target.node, ExprKind::Name { .. }) {
|
||||
return if targets.len() > 1
|
||||
|| contains_effect(value, |id| checker.ctx.is_builtin(id))
|
||||
{
|
||||
return if targets.len() > 1 || contains_effect(&checker.ctx, value) {
|
||||
// If the expression is complex (`x = foo()`), remove the assignment,
|
||||
// but preserve the right-hand side.
|
||||
Some((
|
||||
@@ -250,7 +248,7 @@ fn remove_unused_variable(
|
||||
} = &stmt.node
|
||||
{
|
||||
if matches!(target.node, ExprKind::Name { .. }) {
|
||||
return if contains_effect(value, |id| checker.ctx.is_builtin(id)) {
|
||||
return if contains_effect(&checker.ctx, value) {
|
||||
// If the expression is complex (`x = foo()`), remove the assignment,
|
||||
// but preserve the right-hand side.
|
||||
Some((
|
||||
|
||||
@@ -4,8 +4,8 @@ use rustpython_parser::ast::{Expr, ExprKind};
|
||||
|
||||
use ruff_diagnostics::{Diagnostic, Violation};
|
||||
use ruff_macros::{derive_message_formats, violation};
|
||||
use ruff_python_ast::scope::ScopeKind;
|
||||
use ruff_python_ast::types::Range;
|
||||
use ruff_python_semantic::scope::ScopeKind;
|
||||
|
||||
use crate::checkers::ast::Checker;
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use ruff_python_semantic::analyze::function_type;
|
||||
use ruff_python_semantic::analyze::function_type::FunctionType;
|
||||
use ruff_python_semantic::scope::{FunctionDef, ScopeKind};
|
||||
use ruff_python_ast::function_type;
|
||||
use ruff_python_ast::function_type::FunctionType;
|
||||
use ruff_python_ast::scope::{FunctionDef, ScopeKind};
|
||||
|
||||
use crate::checkers::ast::Checker;
|
||||
|
||||
|
||||
@@ -2,8 +2,8 @@ use rustpython_parser::ast::Expr;
|
||||
|
||||
use ruff_diagnostics::{Diagnostic, Violation};
|
||||
use ruff_macros::{derive_message_formats, violation};
|
||||
use ruff_python_ast::scope::{FunctionDef, ScopeKind};
|
||||
use ruff_python_ast::types::Range;
|
||||
use ruff_python_semantic::scope::{FunctionDef, ScopeKind};
|
||||
|
||||
use crate::checkers::ast::Checker;
|
||||
|
||||
|
||||
@@ -2,8 +2,8 @@ use rustpython_parser::ast::Expr;
|
||||
|
||||
use ruff_diagnostics::{Diagnostic, Violation};
|
||||
use ruff_macros::{derive_message_formats, violation};
|
||||
use ruff_python_ast::scope::ScopeKind;
|
||||
use ruff_python_ast::types::Range;
|
||||
use ruff_python_semantic::scope::ScopeKind;
|
||||
|
||||
use crate::checkers::ast::Checker;
|
||||
|
||||
|
||||
@@ -3,9 +3,8 @@ use rustpython_parser::ast::{Constant, Expr, ExprKind, Keyword};
|
||||
use ruff_diagnostics::{Diagnostic, Violation};
|
||||
use ruff_macros::{derive_message_formats, violation};
|
||||
use ruff_python_ast::helpers::SimpleCallArgs;
|
||||
use ruff_python_ast::logging;
|
||||
use ruff_python_ast::types::Range;
|
||||
use ruff_python_semantic::analyze::logging;
|
||||
use ruff_python_stdlib::logging::LoggingLevel;
|
||||
|
||||
use crate::checkers::ast::Checker;
|
||||
use crate::registry::Rule;
|
||||
@@ -106,7 +105,7 @@ pub fn logging_call(checker: &mut Checker, func: &Expr, args: &[Expr], keywords:
|
||||
}
|
||||
|
||||
if let ExprKind::Attribute { attr, .. } = &func.node {
|
||||
if LoggingLevel::from_attribute(attr.as_str()).is_some() {
|
||||
if logging::LoggingLevel::from_attribute(attr.as_str()).is_some() {
|
||||
let call_args = SimpleCallArgs::new(args, keywords);
|
||||
if let Some(msg) = call_args.argument("msg", 0) {
|
||||
if let ExprKind::Constant {
|
||||
|
||||
@@ -4,7 +4,7 @@ use ruff_diagnostics::{AutofixKind, Diagnostic, Edit, Fix, Violation};
|
||||
use ruff_macros::{derive_message_formats, violation};
|
||||
use ruff_python_ast::types::Range;
|
||||
|
||||
use crate::autofix::actions::get_or_import_symbol;
|
||||
use crate::autofix::helpers::get_or_import_symbol;
|
||||
use crate::checkers::ast::Checker;
|
||||
use crate::registry::AsRule;
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ use ruff_python_ast::helpers::{is_const_none, ReturnStatementVisitor};
|
||||
use ruff_python_ast::types::{Range, RefEquality};
|
||||
use ruff_python_ast::visitor::Visitor;
|
||||
|
||||
use crate::autofix::actions::delete_stmt;
|
||||
use crate::autofix::helpers::delete_stmt;
|
||||
use crate::checkers::ast::Checker;
|
||||
use crate::registry::AsRule;
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ impl AlwaysAutofixableViolation for FormatLiterals {
|
||||
}
|
||||
|
||||
fn autofix_title(&self) -> String {
|
||||
"Remove explicit positional indices".to_string()
|
||||
"Remove explicit positional indexes".to_string()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -135,7 +135,7 @@ pub(crate) fn format_literals(checker: &mut Checker, summary: &FormatSummary, ex
|
||||
if !summary.autos.is_empty() {
|
||||
return;
|
||||
}
|
||||
if !(0..summary.indices.len()).all(|index| summary.indices.contains(&index)) {
|
||||
if !(0..summary.indexes.len()).all(|index| summary.indexes.contains(&index)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -144,7 +144,7 @@ pub(crate) fn format_literals(checker: &mut Checker, summary: &FormatSummary, ex
|
||||
// Currently, the only issue we know of is in LibCST:
|
||||
// https://github.com/Instagram/LibCST/issues/846
|
||||
if let Ok(contents) =
|
||||
generate_call(expr, &summary.indices, checker.locator, checker.stylist)
|
||||
generate_call(expr, &summary.indexes, checker.locator, checker.stylist)
|
||||
{
|
||||
diagnostic.set_fix(Edit::replacement(
|
||||
contents,
|
||||
|
||||
@@ -4,7 +4,7 @@ use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Edit, Fix};
|
||||
use ruff_macros::{derive_message_formats, violation};
|
||||
use ruff_python_ast::types::Range;
|
||||
|
||||
use crate::autofix::actions::get_or_import_symbol;
|
||||
use crate::autofix::helpers::get_or_import_symbol;
|
||||
use crate::checkers::ast::Checker;
|
||||
use crate::registry::AsRule;
|
||||
|
||||
|
||||
@@ -3,9 +3,9 @@ use rustpython_parser::ast::{Excepthandler, ExcepthandlerKind, Expr, ExprContext
|
||||
use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Edit};
|
||||
use ruff_macros::{derive_message_formats, violation};
|
||||
use ruff_python_ast::call_path::compose_call_path;
|
||||
use ruff_python_ast::context::Context;
|
||||
use ruff_python_ast::helpers::{create_expr, unparse_expr};
|
||||
use ruff_python_ast::types::Range;
|
||||
use ruff_python_semantic::context::Context;
|
||||
|
||||
use crate::checkers::ast::Checker;
|
||||
use crate::registry::AsRule;
|
||||
|
||||
@@ -11,7 +11,7 @@ use ruff_python_ast::source_code::Locator;
|
||||
use ruff_python_ast::types::{Range, RefEquality};
|
||||
use ruff_python_ast::whitespace::indentation;
|
||||
|
||||
use crate::autofix::actions::delete_stmt;
|
||||
use crate::autofix::helpers::delete_stmt;
|
||||
use crate::checkers::ast::Checker;
|
||||
use crate::registry::AsRule;
|
||||
use crate::rules::pyupgrade::fixes::adjust_indentation;
|
||||
|
||||
@@ -7,7 +7,7 @@ use ruff_python_ast::helpers::find_keyword;
|
||||
use ruff_python_ast::source_code::Locator;
|
||||
use ruff_python_ast::types::Range;
|
||||
|
||||
use crate::autofix::actions::remove_argument;
|
||||
use crate::autofix::helpers::remove_argument;
|
||||
use crate::checkers::ast::Checker;
|
||||
use crate::registry::AsRule;
|
||||
|
||||
|
||||
@@ -2,8 +2,8 @@ use rustpython_parser::ast::{ArgData, Expr, ExprKind, Stmt, StmtKind};
|
||||
|
||||
use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic};
|
||||
use ruff_macros::{derive_message_formats, violation};
|
||||
use ruff_python_ast::scope::ScopeKind;
|
||||
use ruff_python_ast::types::Range;
|
||||
use ruff_python_semantic::scope::ScopeKind;
|
||||
|
||||
use crate::checkers::ast::Checker;
|
||||
use crate::registry::AsRule;
|
||||
|
||||
@@ -112,7 +112,7 @@ pub fn unnecessary_builtin_import(
|
||||
.iter()
|
||||
.map(|alias| format!("{module}.{}", alias.node.name))
|
||||
.collect();
|
||||
match autofix::actions::remove_unused_imports(
|
||||
match autofix::helpers::remove_unused_imports(
|
||||
unused_imports.iter().map(String::as_str),
|
||||
defined_by.into(),
|
||||
defined_in.map(Into::into),
|
||||
|
||||
@@ -6,7 +6,7 @@ use ruff_macros::{derive_message_formats, violation};
|
||||
use ruff_python_ast::source_code::Locator;
|
||||
use ruff_python_ast::types::Range;
|
||||
|
||||
use crate::autofix::actions::remove_argument;
|
||||
use crate::autofix::helpers::remove_argument;
|
||||
use crate::checkers::ast::Checker;
|
||||
use crate::registry::Rule;
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user