mirror of
https://github.com/astral-sh/ruff.git
synced 2025-08-18 09:30:35 +00:00
Move a few more candidate rules to the deferred Binding
-only pass (#5853)
## Summary No behavior change, but this is in theory more efficient, since we can just iterate over the flat `Binding` vector rather than having to iterate over binding chains via the `Scope`.
This commit is contained in:
parent
626d8dc2cc
commit
1181d25e5a
5 changed files with 86 additions and 81 deletions
|
@ -4776,7 +4776,11 @@ impl<'a> Checker<'a> {
|
||||||
|
|
||||||
/// Run any lint rules that operate over a single [`Binding`].
|
/// Run any lint rules that operate over a single [`Binding`].
|
||||||
fn check_bindings(&mut self) {
|
fn check_bindings(&mut self) {
|
||||||
if !self.any_enabled(&[Rule::UnusedVariable]) {
|
if !self.any_enabled(&[
|
||||||
|
Rule::UnusedVariable,
|
||||||
|
Rule::UnconventionalImportAlias,
|
||||||
|
Rule::UnaliasedCollectionsAbcSetImport,
|
||||||
|
]) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4802,6 +4806,27 @@ impl<'a> Checker<'a> {
|
||||||
self.diagnostics.push(diagnostic);
|
self.diagnostics.push(diagnostic);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if self.enabled(Rule::UnconventionalImportAlias) {
|
||||||
|
if let Some(diagnostic) =
|
||||||
|
flake8_import_conventions::rules::unconventional_import_alias(
|
||||||
|
self,
|
||||||
|
binding,
|
||||||
|
&self.settings.flake8_import_conventions.aliases,
|
||||||
|
)
|
||||||
|
{
|
||||||
|
self.diagnostics.push(diagnostic);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if self.is_stub {
|
||||||
|
if self.enabled(Rule::UnaliasedCollectionsAbcSetImport) {
|
||||||
|
if let Some(diagnostic) =
|
||||||
|
flake8_pyi::rules::unaliased_collections_abc_set_import(self, binding)
|
||||||
|
{
|
||||||
|
self.diagnostics.push(diagnostic);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4814,8 +4839,6 @@ impl<'a> Checker<'a> {
|
||||||
Rule::TypingOnlyFirstPartyImport,
|
Rule::TypingOnlyFirstPartyImport,
|
||||||
Rule::TypingOnlyStandardLibraryImport,
|
Rule::TypingOnlyStandardLibraryImport,
|
||||||
Rule::TypingOnlyThirdPartyImport,
|
Rule::TypingOnlyThirdPartyImport,
|
||||||
Rule::UnaliasedCollectionsAbcSetImport,
|
|
||||||
Rule::UnconventionalImportAlias,
|
|
||||||
Rule::UndefinedExport,
|
Rule::UndefinedExport,
|
||||||
Rule::UndefinedLocalWithImportStarUsage,
|
Rule::UndefinedLocalWithImportStarUsage,
|
||||||
Rule::UndefinedLocalWithImportStarUsage,
|
Rule::UndefinedLocalWithImportStarUsage,
|
||||||
|
@ -5115,23 +5138,6 @@ impl<'a> Checker<'a> {
|
||||||
if self.enabled(Rule::UnusedImport) {
|
if self.enabled(Rule::UnusedImport) {
|
||||||
pyflakes::rules::unused_import(self, scope, &mut diagnostics);
|
pyflakes::rules::unused_import(self, scope, &mut diagnostics);
|
||||||
}
|
}
|
||||||
if self.enabled(Rule::UnconventionalImportAlias) {
|
|
||||||
flake8_import_conventions::rules::unconventional_import_alias(
|
|
||||||
self,
|
|
||||||
scope,
|
|
||||||
&mut diagnostics,
|
|
||||||
&self.settings.flake8_import_conventions.aliases,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
if self.is_stub {
|
|
||||||
if self.enabled(Rule::UnaliasedCollectionsAbcSetImport) {
|
|
||||||
flake8_pyi::rules::unaliased_collections_abc_set_import(
|
|
||||||
self,
|
|
||||||
scope,
|
|
||||||
&mut diagnostics,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
self.diagnostics.extend(diagnostics);
|
self.diagnostics.extend(diagnostics);
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@ use rustc_hash::FxHashMap;
|
||||||
|
|
||||||
use ruff_diagnostics::{AutofixKind, Diagnostic, Fix, Violation};
|
use ruff_diagnostics::{AutofixKind, Diagnostic, Fix, Violation};
|
||||||
use ruff_macros::{derive_message_formats, violation};
|
use ruff_macros::{derive_message_formats, violation};
|
||||||
use ruff_python_semantic::Scope;
|
use ruff_python_semantic::Binding;
|
||||||
|
|
||||||
use crate::checkers::ast::Checker;
|
use crate::checkers::ast::Checker;
|
||||||
use crate::registry::AsRule;
|
use crate::registry::AsRule;
|
||||||
|
@ -53,23 +53,20 @@ impl Violation for UnconventionalImportAlias {
|
||||||
/// ICN001
|
/// ICN001
|
||||||
pub(crate) fn unconventional_import_alias(
|
pub(crate) fn unconventional_import_alias(
|
||||||
checker: &Checker,
|
checker: &Checker,
|
||||||
scope: &Scope,
|
binding: &Binding,
|
||||||
diagnostics: &mut Vec<Diagnostic>,
|
|
||||||
conventions: &FxHashMap<String, String>,
|
conventions: &FxHashMap<String, String>,
|
||||||
) -> Option<Diagnostic> {
|
) -> Option<Diagnostic> {
|
||||||
for (name, binding_id) in scope.all_bindings() {
|
|
||||||
let binding = checker.semantic().binding(binding_id);
|
|
||||||
|
|
||||||
let Some(qualified_name) = binding.qualified_name() else {
|
let Some(qualified_name) = binding.qualified_name() else {
|
||||||
continue;
|
return None;
|
||||||
};
|
};
|
||||||
|
|
||||||
let Some(expected_alias) = conventions.get(qualified_name) else {
|
let Some(expected_alias) = conventions.get(qualified_name) else {
|
||||||
continue;
|
return None;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let name = binding.name(checker.locator);
|
||||||
if binding.is_alias() && name == expected_alias {
|
if binding.is_alias() && name == expected_alias {
|
||||||
continue;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut diagnostic = Diagnostic::new(
|
let mut diagnostic = Diagnostic::new(
|
||||||
|
@ -82,13 +79,12 @@ pub(crate) fn unconventional_import_alias(
|
||||||
if checker.patch(diagnostic.kind.rule()) {
|
if checker.patch(diagnostic.kind.rule()) {
|
||||||
if checker.semantic().is_available(expected_alias) {
|
if checker.semantic().is_available(expected_alias) {
|
||||||
diagnostic.try_set_fix(|| {
|
diagnostic.try_set_fix(|| {
|
||||||
|
let scope = &checker.semantic().scopes[binding.scope];
|
||||||
let (edit, rest) =
|
let (edit, rest) =
|
||||||
Renamer::rename(name, expected_alias, scope, checker.semantic())?;
|
Renamer::rename(name, expected_alias, scope, checker.semantic())?;
|
||||||
Ok(Fix::suggested_edits(edit, rest))
|
Ok(Fix::suggested_edits(edit, rest))
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
diagnostics.push(diagnostic);
|
Some(diagnostic)
|
||||||
}
|
|
||||||
None
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use ruff_diagnostics::{AutofixKind, Diagnostic, Fix, Violation};
|
use ruff_diagnostics::{AutofixKind, Diagnostic, Fix, Violation};
|
||||||
use ruff_macros::{derive_message_formats, violation};
|
use ruff_macros::{derive_message_formats, violation};
|
||||||
use ruff_python_semantic::{BindingKind, FromImport, Scope};
|
use ruff_python_semantic::{Binding, BindingKind, FromImport};
|
||||||
|
|
||||||
use crate::checkers::ast::Checker;
|
use crate::checkers::ast::Checker;
|
||||||
use crate::registry::AsRule;
|
use crate::registry::AsRule;
|
||||||
|
@ -48,31 +48,29 @@ impl Violation for UnaliasedCollectionsAbcSetImport {
|
||||||
/// PYI025
|
/// PYI025
|
||||||
pub(crate) fn unaliased_collections_abc_set_import(
|
pub(crate) fn unaliased_collections_abc_set_import(
|
||||||
checker: &Checker,
|
checker: &Checker,
|
||||||
scope: &Scope,
|
binding: &Binding,
|
||||||
diagnostics: &mut Vec<Diagnostic>,
|
) -> Option<Diagnostic> {
|
||||||
) {
|
|
||||||
for (name, binding_id) in scope.all_bindings() {
|
|
||||||
let binding = checker.semantic().binding(binding_id);
|
|
||||||
let BindingKind::FromImport(FromImport { qualified_name }) = &binding.kind else {
|
let BindingKind::FromImport(FromImport { qualified_name }) = &binding.kind else {
|
||||||
continue;
|
return None;
|
||||||
};
|
};
|
||||||
if qualified_name.as_str() != "collections.abc.Set" {
|
if qualified_name.as_str() != "collections.abc.Set" {
|
||||||
continue;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let name = binding.name(checker.locator);
|
||||||
if name == "AbstractSet" {
|
if name == "AbstractSet" {
|
||||||
continue;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut diagnostic = Diagnostic::new(UnaliasedCollectionsAbcSetImport, binding.range);
|
let mut diagnostic = Diagnostic::new(UnaliasedCollectionsAbcSetImport, binding.range);
|
||||||
if checker.patch(diagnostic.kind.rule()) {
|
if checker.patch(diagnostic.kind.rule()) {
|
||||||
if checker.semantic().is_available("AbstractSet") {
|
if checker.semantic().is_available("AbstractSet") {
|
||||||
diagnostic.try_set_fix(|| {
|
diagnostic.try_set_fix(|| {
|
||||||
let (edit, rest) =
|
let scope = &checker.semantic().scopes[binding.scope];
|
||||||
Renamer::rename(name, "AbstractSet", scope, checker.semantic())?;
|
let (edit, rest) = Renamer::rename(name, "AbstractSet", scope, checker.semantic())?;
|
||||||
Ok(Fix::suggested_edits(edit, rest))
|
Ok(Fix::suggested_edits(edit, rest))
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
diagnostics.push(diagnostic);
|
Some(diagnostic)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,8 @@ use crate::ScopeId;
|
||||||
pub struct Binding<'a> {
|
pub struct Binding<'a> {
|
||||||
pub kind: BindingKind<'a>,
|
pub kind: BindingKind<'a>,
|
||||||
pub range: TextRange,
|
pub range: TextRange,
|
||||||
|
/// The [`ScopeId`] of the scope in which the [`Binding`] was defined.
|
||||||
|
pub scope: ScopeId,
|
||||||
/// The context in which the [`Binding`] was created.
|
/// The context in which the [`Binding`] was created.
|
||||||
pub context: ExecutionContext,
|
pub context: ExecutionContext,
|
||||||
/// The statement in which the [`Binding`] was defined.
|
/// The statement in which the [`Binding`] was defined.
|
||||||
|
|
|
@ -189,6 +189,7 @@ impl<'a> SemanticModel<'a> {
|
||||||
self.bindings.push(Binding {
|
self.bindings.push(Binding {
|
||||||
range: TextRange::default(),
|
range: TextRange::default(),
|
||||||
kind: BindingKind::Builtin,
|
kind: BindingKind::Builtin,
|
||||||
|
scope: ScopeId::global(),
|
||||||
references: Vec::new(),
|
references: Vec::new(),
|
||||||
flags: BindingFlags::empty(),
|
flags: BindingFlags::empty(),
|
||||||
source: None,
|
source: None,
|
||||||
|
@ -209,6 +210,7 @@ impl<'a> SemanticModel<'a> {
|
||||||
kind,
|
kind,
|
||||||
flags,
|
flags,
|
||||||
references: Vec::new(),
|
references: Vec::new(),
|
||||||
|
scope: self.scope_id,
|
||||||
source: self.stmt_id,
|
source: self.stmt_id,
|
||||||
context: self.execution_context(),
|
context: self.execution_context(),
|
||||||
exceptions: self.exceptions(),
|
exceptions: self.exceptions(),
|
||||||
|
@ -795,6 +797,7 @@ impl<'a> SemanticModel<'a> {
|
||||||
kind: BindingKind::Assignment,
|
kind: BindingKind::Assignment,
|
||||||
range: *range,
|
range: *range,
|
||||||
references: Vec::new(),
|
references: Vec::new(),
|
||||||
|
scope: self.scope_id,
|
||||||
source: self.stmt_id,
|
source: self.stmt_id,
|
||||||
context: self.execution_context(),
|
context: self.execution_context(),
|
||||||
exceptions: self.exceptions(),
|
exceptions: self.exceptions(),
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue