mirror of
https://github.com/astral-sh/ruff.git
synced 2025-08-19 01:50:38 +00:00
Remove ReferenceContext::Synthetic
(#4612)
This commit is contained in:
parent
38297c08b4
commit
5cedf0f724
8 changed files with 110 additions and 98 deletions
4
crates/ruff/resources/test/fixtures/pyflakes/F811_23.py
vendored
Normal file
4
crates/ruff/resources/test/fixtures/pyflakes/F811_23.py
vendored
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
"""Test that shadowing an explicit re-export produces a warning."""
|
||||||
|
|
||||||
|
import foo as foo
|
||||||
|
import bar as foo
|
5
crates/ruff/resources/test/fixtures/pyflakes/F811_24.py
vendored
Normal file
5
crates/ruff/resources/test/fixtures/pyflakes/F811_24.py
vendored
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
"""Test that shadowing a `__future__` import does not produce a warning."""
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import annotations
|
|
@ -24,8 +24,8 @@ use ruff_python_semantic::analyze::branch_detection;
|
||||||
use ruff_python_semantic::analyze::typing::{Callable, SubscriptKind};
|
use ruff_python_semantic::analyze::typing::{Callable, SubscriptKind};
|
||||||
use ruff_python_semantic::analyze::visibility::ModuleSource;
|
use ruff_python_semantic::analyze::visibility::ModuleSource;
|
||||||
use ruff_python_semantic::binding::{
|
use ruff_python_semantic::binding::{
|
||||||
Binding, BindingId, BindingKind, Exceptions, ExecutionContext, Export, FromImportation,
|
Binding, BindingFlags, BindingId, BindingKind, Exceptions, ExecutionContext, Export,
|
||||||
Importation, StarImportation, SubmoduleImportation,
|
FromImportation, Importation, StarImportation, SubmoduleImportation,
|
||||||
};
|
};
|
||||||
use ruff_python_semantic::definition::{ContextualizedDefinition, Module, ModuleKind};
|
use ruff_python_semantic::definition::{ContextualizedDefinition, Module, ModuleKind};
|
||||||
use ruff_python_semantic::model::{ResolvedReference, SemanticModel, SemanticModelFlags};
|
use ruff_python_semantic::model::{ResolvedReference, SemanticModel, SemanticModelFlags};
|
||||||
|
@ -235,6 +235,7 @@ where
|
||||||
// Add the binding to the current scope.
|
// Add the binding to the current scope.
|
||||||
let context = self.semantic_model.execution_context();
|
let context = self.semantic_model.execution_context();
|
||||||
let exceptions = self.semantic_model.exceptions();
|
let exceptions = self.semantic_model.exceptions();
|
||||||
|
let scope = &mut self.semantic_model.scopes[self.semantic_model.scope_id];
|
||||||
for (name, range) in names.iter().zip(ranges.iter()) {
|
for (name, range) in names.iter().zip(ranges.iter()) {
|
||||||
// Add a binding to the current scope.
|
// Add a binding to the current scope.
|
||||||
let binding_id = self.semantic_model.bindings.push(Binding {
|
let binding_id = self.semantic_model.bindings.push(Binding {
|
||||||
|
@ -244,16 +245,8 @@ where
|
||||||
source: self.semantic_model.stmt_id,
|
source: self.semantic_model.stmt_id,
|
||||||
context,
|
context,
|
||||||
exceptions,
|
exceptions,
|
||||||
|
flags: BindingFlags::empty(),
|
||||||
});
|
});
|
||||||
|
|
||||||
// Add a reference to the global binding.
|
|
||||||
self.semantic_model.add_local_reference(
|
|
||||||
binding_id,
|
|
||||||
stmt.range(),
|
|
||||||
ReferenceContext::Synthetic,
|
|
||||||
);
|
|
||||||
|
|
||||||
let scope = &mut self.semantic_model.scopes[self.semantic_model.scope_id];
|
|
||||||
scope.add(name, binding_id);
|
scope.add(name, binding_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -270,6 +263,7 @@ where
|
||||||
if !self.semantic_model.scope_id.is_global() {
|
if !self.semantic_model.scope_id.is_global() {
|
||||||
let context = self.semantic_model.execution_context();
|
let context = self.semantic_model.execution_context();
|
||||||
let exceptions = self.semantic_model.exceptions();
|
let exceptions = self.semantic_model.exceptions();
|
||||||
|
let scope = &mut self.semantic_model.scopes[self.semantic_model.scope_id];
|
||||||
for (name, range) in names.iter().zip(ranges.iter()) {
|
for (name, range) in names.iter().zip(ranges.iter()) {
|
||||||
// Add a binding to the current scope.
|
// Add a binding to the current scope.
|
||||||
let binding_id = self.semantic_model.bindings.push(Binding {
|
let binding_id = self.semantic_model.bindings.push(Binding {
|
||||||
|
@ -279,16 +273,8 @@ where
|
||||||
source: self.semantic_model.stmt_id,
|
source: self.semantic_model.stmt_id,
|
||||||
context,
|
context,
|
||||||
exceptions,
|
exceptions,
|
||||||
|
flags: BindingFlags::empty(),
|
||||||
});
|
});
|
||||||
|
|
||||||
// Add a reference to the global binding.
|
|
||||||
self.semantic_model.add_local_reference(
|
|
||||||
binding_id,
|
|
||||||
stmt.range(),
|
|
||||||
ReferenceContext::Synthetic,
|
|
||||||
);
|
|
||||||
|
|
||||||
let scope = &mut self.semantic_model.scopes[self.semantic_model.scope_id];
|
|
||||||
scope.add(name, binding_id);
|
scope.add(name, binding_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -814,7 +800,7 @@ where
|
||||||
if &alias.name == "__future__" {
|
if &alias.name == "__future__" {
|
||||||
let name = alias.asname.as_ref().unwrap_or(&alias.name);
|
let name = alias.asname.as_ref().unwrap_or(&alias.name);
|
||||||
|
|
||||||
let binding_id = self.add_binding(
|
self.add_binding(
|
||||||
name,
|
name,
|
||||||
Binding {
|
Binding {
|
||||||
kind: BindingKind::FutureImportation,
|
kind: BindingKind::FutureImportation,
|
||||||
|
@ -823,16 +809,10 @@ where
|
||||||
source: self.semantic_model.stmt_id,
|
source: self.semantic_model.stmt_id,
|
||||||
context: self.semantic_model.execution_context(),
|
context: self.semantic_model.execution_context(),
|
||||||
exceptions: self.semantic_model.exceptions(),
|
exceptions: self.semantic_model.exceptions(),
|
||||||
|
flags: BindingFlags::empty(),
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
// Always mark `__future__` imports as used.
|
|
||||||
self.semantic_model.add_local_reference(
|
|
||||||
binding_id,
|
|
||||||
alias.range(),
|
|
||||||
ReferenceContext::Synthetic,
|
|
||||||
);
|
|
||||||
|
|
||||||
if self.enabled(Rule::LateFutureImport) {
|
if self.enabled(Rule::LateFutureImport) {
|
||||||
if self.semantic_model.seen_futures_boundary() {
|
if self.semantic_model.seen_futures_boundary() {
|
||||||
self.diagnostics.push(Diagnostic::new(
|
self.diagnostics.push(Diagnostic::new(
|
||||||
|
@ -858,12 +838,13 @@ where
|
||||||
source: self.semantic_model.stmt_id,
|
source: self.semantic_model.stmt_id,
|
||||||
context: self.semantic_model.execution_context(),
|
context: self.semantic_model.execution_context(),
|
||||||
exceptions: self.semantic_model.exceptions(),
|
exceptions: self.semantic_model.exceptions(),
|
||||||
|
flags: BindingFlags::empty(),
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
let name = alias.asname.as_ref().unwrap_or(&alias.name);
|
let name = alias.asname.as_ref().unwrap_or(&alias.name);
|
||||||
let full_name = &alias.name;
|
let full_name = &alias.name;
|
||||||
let binding_id = self.add_binding(
|
self.add_binding(
|
||||||
name,
|
name,
|
||||||
Binding {
|
Binding {
|
||||||
kind: BindingKind::Importation(Importation { name, full_name }),
|
kind: BindingKind::Importation(Importation { name, full_name }),
|
||||||
|
@ -872,23 +853,18 @@ where
|
||||||
source: self.semantic_model.stmt_id,
|
source: self.semantic_model.stmt_id,
|
||||||
context: self.semantic_model.execution_context(),
|
context: self.semantic_model.execution_context(),
|
||||||
exceptions: self.semantic_model.exceptions(),
|
exceptions: self.semantic_model.exceptions(),
|
||||||
|
flags: if alias
|
||||||
|
.asname
|
||||||
|
.as_ref()
|
||||||
|
.map_or(false, |asname| asname == &alias.name)
|
||||||
|
{
|
||||||
|
BindingFlags::EXPLICIT_EXPORT
|
||||||
|
} else {
|
||||||
|
BindingFlags::empty()
|
||||||
|
},
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
// Treat explicit re-export as usage (e.g., `from .applications
|
|
||||||
// import FastAPI as FastAPI`).
|
|
||||||
let is_explicit_reexport = alias
|
|
||||||
.asname
|
|
||||||
.as_ref()
|
|
||||||
.map_or(false, |asname| asname == &alias.name);
|
|
||||||
if is_explicit_reexport {
|
|
||||||
self.semantic_model.add_local_reference(
|
|
||||||
binding_id,
|
|
||||||
alias.range(),
|
|
||||||
ReferenceContext::Synthetic,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(asname) = &alias.asname {
|
if let Some(asname) = &alias.asname {
|
||||||
if self.enabled(Rule::BuiltinVariableShadowing) {
|
if self.enabled(Rule::BuiltinVariableShadowing) {
|
||||||
flake8_builtins::rules::builtin_variable_shadowing(
|
flake8_builtins::rules::builtin_variable_shadowing(
|
||||||
|
@ -1103,7 +1079,7 @@ where
|
||||||
if let Some("__future__") = module {
|
if let Some("__future__") = module {
|
||||||
let name = alias.asname.as_ref().unwrap_or(&alias.name);
|
let name = alias.asname.as_ref().unwrap_or(&alias.name);
|
||||||
|
|
||||||
let binding_id = self.add_binding(
|
self.add_binding(
|
||||||
name,
|
name,
|
||||||
Binding {
|
Binding {
|
||||||
kind: BindingKind::FutureImportation,
|
kind: BindingKind::FutureImportation,
|
||||||
|
@ -1112,16 +1088,10 @@ where
|
||||||
source: self.semantic_model.stmt_id,
|
source: self.semantic_model.stmt_id,
|
||||||
context: self.semantic_model.execution_context(),
|
context: self.semantic_model.execution_context(),
|
||||||
exceptions: self.semantic_model.exceptions(),
|
exceptions: self.semantic_model.exceptions(),
|
||||||
|
flags: BindingFlags::empty(),
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
// Always mark `__future__` imports as used.
|
|
||||||
self.semantic_model.add_local_reference(
|
|
||||||
binding_id,
|
|
||||||
alias.range(),
|
|
||||||
ReferenceContext::Synthetic,
|
|
||||||
);
|
|
||||||
|
|
||||||
if self.enabled(Rule::FutureFeatureNotDefined) {
|
if self.enabled(Rule::FutureFeatureNotDefined) {
|
||||||
pyflakes::rules::future_feature_not_defined(self, alias);
|
pyflakes::rules::future_feature_not_defined(self, alias);
|
||||||
}
|
}
|
||||||
|
@ -1176,7 +1146,7 @@ where
|
||||||
let name = alias.asname.as_ref().unwrap_or(&alias.name);
|
let name = alias.asname.as_ref().unwrap_or(&alias.name);
|
||||||
let full_name =
|
let full_name =
|
||||||
helpers::format_import_from_member(level, module, &alias.name);
|
helpers::format_import_from_member(level, module, &alias.name);
|
||||||
let binding_id = self.add_binding(
|
self.add_binding(
|
||||||
name,
|
name,
|
||||||
Binding {
|
Binding {
|
||||||
kind: BindingKind::FromImportation(FromImportation {
|
kind: BindingKind::FromImportation(FromImportation {
|
||||||
|
@ -1188,22 +1158,17 @@ where
|
||||||
source: self.semantic_model.stmt_id,
|
source: self.semantic_model.stmt_id,
|
||||||
context: self.semantic_model.execution_context(),
|
context: self.semantic_model.execution_context(),
|
||||||
exceptions: self.semantic_model.exceptions(),
|
exceptions: self.semantic_model.exceptions(),
|
||||||
|
flags: if alias
|
||||||
|
.asname
|
||||||
|
.as_ref()
|
||||||
|
.map_or(false, |asname| asname == &alias.name)
|
||||||
|
{
|
||||||
|
BindingFlags::EXPLICIT_EXPORT
|
||||||
|
} else {
|
||||||
|
BindingFlags::empty()
|
||||||
|
},
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
// Treat explicit re-export as usage (e.g., `from .applications
|
|
||||||
// import FastAPI as FastAPI`).
|
|
||||||
let is_explicit_reexport = alias
|
|
||||||
.asname
|
|
||||||
.as_ref()
|
|
||||||
.map_or(false, |asname| asname == &alias.name);
|
|
||||||
if is_explicit_reexport {
|
|
||||||
self.semantic_model.add_local_reference(
|
|
||||||
binding_id,
|
|
||||||
alias.range(),
|
|
||||||
ReferenceContext::Synthetic,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.enabled(Rule::RelativeImports) {
|
if self.enabled(Rule::RelativeImports) {
|
||||||
|
@ -1914,6 +1879,7 @@ where
|
||||||
source: self.semantic_model.stmt_id,
|
source: self.semantic_model.stmt_id,
|
||||||
context: self.semantic_model.execution_context(),
|
context: self.semantic_model.execution_context(),
|
||||||
exceptions: self.semantic_model.exceptions(),
|
exceptions: self.semantic_model.exceptions(),
|
||||||
|
flags: BindingFlags::empty(),
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -1937,6 +1903,7 @@ where
|
||||||
source: self.semantic_model.stmt_id,
|
source: self.semantic_model.stmt_id,
|
||||||
context: self.semantic_model.execution_context(),
|
context: self.semantic_model.execution_context(),
|
||||||
exceptions: self.semantic_model.exceptions(),
|
exceptions: self.semantic_model.exceptions(),
|
||||||
|
flags: BindingFlags::empty(),
|
||||||
});
|
});
|
||||||
self.semantic_model.global_scope_mut().add(name, id);
|
self.semantic_model.global_scope_mut().add(name, id);
|
||||||
}
|
}
|
||||||
|
@ -2000,6 +1967,7 @@ where
|
||||||
source: self.semantic_model.stmt_id,
|
source: self.semantic_model.stmt_id,
|
||||||
context: self.semantic_model.execution_context(),
|
context: self.semantic_model.execution_context(),
|
||||||
exceptions: self.semantic_model.exceptions(),
|
exceptions: self.semantic_model.exceptions(),
|
||||||
|
flags: BindingFlags::empty(),
|
||||||
});
|
});
|
||||||
self.semantic_model.global_scope_mut().add(name, id);
|
self.semantic_model.global_scope_mut().add(name, id);
|
||||||
}
|
}
|
||||||
|
@ -2186,6 +2154,7 @@ where
|
||||||
source: self.semantic_model.stmt_id,
|
source: self.semantic_model.stmt_id,
|
||||||
context: self.semantic_model.execution_context(),
|
context: self.semantic_model.execution_context(),
|
||||||
exceptions: self.semantic_model.exceptions(),
|
exceptions: self.semantic_model.exceptions(),
|
||||||
|
flags: BindingFlags::empty(),
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -4147,6 +4116,7 @@ where
|
||||||
source: self.semantic_model.stmt_id,
|
source: self.semantic_model.stmt_id,
|
||||||
context: self.semantic_model.execution_context(),
|
context: self.semantic_model.execution_context(),
|
||||||
exceptions: self.semantic_model.exceptions(),
|
exceptions: self.semantic_model.exceptions(),
|
||||||
|
flags: BindingFlags::empty(),
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -4194,6 +4164,7 @@ where
|
||||||
source: self.semantic_model.stmt_id,
|
source: self.semantic_model.stmt_id,
|
||||||
context: self.semantic_model.execution_context(),
|
context: self.semantic_model.execution_context(),
|
||||||
exceptions: self.semantic_model.exceptions(),
|
exceptions: self.semantic_model.exceptions(),
|
||||||
|
flags: BindingFlags::empty(),
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -4459,6 +4430,7 @@ impl<'a> Checker<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn bind_builtins(&mut self) {
|
fn bind_builtins(&mut self) {
|
||||||
|
let scope = &mut self.semantic_model.scopes[self.semantic_model.scope_id];
|
||||||
for builtin in BUILTINS
|
for builtin in BUILTINS
|
||||||
.iter()
|
.iter()
|
||||||
.chain(MAGIC_GLOBALS.iter())
|
.chain(MAGIC_GLOBALS.iter())
|
||||||
|
@ -4473,16 +4445,8 @@ impl<'a> Checker<'a> {
|
||||||
references: Vec::new(),
|
references: Vec::new(),
|
||||||
context: ExecutionContext::Runtime,
|
context: ExecutionContext::Runtime,
|
||||||
exceptions: Exceptions::empty(),
|
exceptions: Exceptions::empty(),
|
||||||
|
flags: BindingFlags::empty(),
|
||||||
});
|
});
|
||||||
|
|
||||||
// Add a reference to the builtin.
|
|
||||||
self.semantic_model.add_global_reference(
|
|
||||||
binding_id,
|
|
||||||
TextRange::default(),
|
|
||||||
ReferenceContext::Synthetic,
|
|
||||||
);
|
|
||||||
|
|
||||||
let scope = &mut self.semantic_model.scopes[self.semantic_model.scope_id];
|
|
||||||
scope.add(builtin, binding_id);
|
scope.add(builtin, binding_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4601,6 +4565,7 @@ impl<'a> Checker<'a> {
|
||||||
source: self.semantic_model.stmt_id,
|
source: self.semantic_model.stmt_id,
|
||||||
context: self.semantic_model.execution_context(),
|
context: self.semantic_model.execution_context(),
|
||||||
exceptions: self.semantic_model.exceptions(),
|
exceptions: self.semantic_model.exceptions(),
|
||||||
|
flags: BindingFlags::empty(),
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
|
@ -4616,6 +4581,7 @@ impl<'a> Checker<'a> {
|
||||||
source: self.semantic_model.stmt_id,
|
source: self.semantic_model.stmt_id,
|
||||||
context: self.semantic_model.execution_context(),
|
context: self.semantic_model.execution_context(),
|
||||||
exceptions: self.semantic_model.exceptions(),
|
exceptions: self.semantic_model.exceptions(),
|
||||||
|
flags: BindingFlags::empty(),
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
|
@ -4631,6 +4597,7 @@ impl<'a> Checker<'a> {
|
||||||
source: self.semantic_model.stmt_id,
|
source: self.semantic_model.stmt_id,
|
||||||
context: self.semantic_model.execution_context(),
|
context: self.semantic_model.execution_context(),
|
||||||
exceptions: self.semantic_model.exceptions(),
|
exceptions: self.semantic_model.exceptions(),
|
||||||
|
flags: BindingFlags::empty(),
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
|
@ -4710,6 +4677,7 @@ impl<'a> Checker<'a> {
|
||||||
source: self.semantic_model.stmt_id,
|
source: self.semantic_model.stmt_id,
|
||||||
context: self.semantic_model.execution_context(),
|
context: self.semantic_model.execution_context(),
|
||||||
exceptions: self.semantic_model.exceptions(),
|
exceptions: self.semantic_model.exceptions(),
|
||||||
|
flags: BindingFlags::empty(),
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
|
@ -4730,6 +4698,7 @@ impl<'a> Checker<'a> {
|
||||||
source: self.semantic_model.stmt_id,
|
source: self.semantic_model.stmt_id,
|
||||||
context: self.semantic_model.execution_context(),
|
context: self.semantic_model.execution_context(),
|
||||||
exceptions: self.semantic_model.exceptions(),
|
exceptions: self.semantic_model.exceptions(),
|
||||||
|
flags: BindingFlags::empty(),
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
|
@ -4744,6 +4713,7 @@ impl<'a> Checker<'a> {
|
||||||
source: self.semantic_model.stmt_id,
|
source: self.semantic_model.stmt_id,
|
||||||
context: self.semantic_model.execution_context(),
|
context: self.semantic_model.execution_context(),
|
||||||
exceptions: self.semantic_model.exceptions(),
|
exceptions: self.semantic_model.exceptions(),
|
||||||
|
flags: BindingFlags::empty(),
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -4961,7 +4931,8 @@ impl<'a> Checker<'a> {
|
||||||
let global_scope = self.semantic_model.global_scope();
|
let global_scope = self.semantic_model.global_scope();
|
||||||
let all_names: Option<(&[&str], TextRange)> = global_scope
|
let all_names: Option<(&[&str], TextRange)> = global_scope
|
||||||
.get("__all__")
|
.get("__all__")
|
||||||
.map(|binding_id| &self.semantic_model.bindings[*binding_id])
|
.copied()
|
||||||
|
.map(|binding_id| &self.semantic_model.bindings[binding_id])
|
||||||
.and_then(|binding| match &binding.kind {
|
.and_then(|binding| match &binding.kind {
|
||||||
BindingKind::Export(Export { names }) => {
|
BindingKind::Export(Export { names }) => {
|
||||||
Some((names.as_slice(), binding.range))
|
Some((names.as_slice(), binding.range))
|
||||||
|
@ -4995,7 +4966,8 @@ impl<'a> Checker<'a> {
|
||||||
.semantic_model
|
.semantic_model
|
||||||
.global_scope()
|
.global_scope()
|
||||||
.get("__all__")
|
.get("__all__")
|
||||||
.map(|binding_id| &self.semantic_model.bindings[*binding_id])
|
.copied()
|
||||||
|
.map(|binding_id| &self.semantic_model.bindings[binding_id])
|
||||||
.and_then(|binding| match &binding.kind {
|
.and_then(|binding| match &binding.kind {
|
||||||
BindingKind::Export(Export { names }) => Some((names.as_slice(), binding.range)),
|
BindingKind::Export(Export { names }) => Some((names.as_slice(), binding.range)),
|
||||||
_ => None,
|
_ => None,
|
||||||
|
@ -5109,7 +5081,6 @@ impl<'a> Checker<'a> {
|
||||||
BindingKind::Importation(..)
|
BindingKind::Importation(..)
|
||||||
| BindingKind::FromImportation(..)
|
| BindingKind::FromImportation(..)
|
||||||
| BindingKind::SubmoduleImportation(..)
|
| BindingKind::SubmoduleImportation(..)
|
||||||
| BindingKind::FutureImportation
|
|
||||||
) {
|
) {
|
||||||
if binding.is_used() {
|
if binding.is_used() {
|
||||||
continue;
|
continue;
|
||||||
|
@ -5202,7 +5173,7 @@ impl<'a> Checker<'a> {
|
||||||
for binding_id in scope.binding_ids() {
|
for binding_id in scope.binding_ids() {
|
||||||
let binding = &self.semantic_model.bindings[*binding_id];
|
let binding = &self.semantic_model.bindings[*binding_id];
|
||||||
|
|
||||||
if binding.is_used() {
|
if binding.is_used() || binding.is_explicit_export() {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -99,6 +99,8 @@ mod tests {
|
||||||
#[test_case(Rule::RedefinedWhileUnused, Path::new("F811_20.py"); "F811_20")]
|
#[test_case(Rule::RedefinedWhileUnused, Path::new("F811_20.py"); "F811_20")]
|
||||||
#[test_case(Rule::RedefinedWhileUnused, Path::new("F811_21.py"); "F811_21")]
|
#[test_case(Rule::RedefinedWhileUnused, Path::new("F811_21.py"); "F811_21")]
|
||||||
#[test_case(Rule::RedefinedWhileUnused, Path::new("F811_22.py"); "F811_22")]
|
#[test_case(Rule::RedefinedWhileUnused, Path::new("F811_22.py"); "F811_22")]
|
||||||
|
#[test_case(Rule::RedefinedWhileUnused, Path::new("F811_23.py"); "F811_23")]
|
||||||
|
#[test_case(Rule::RedefinedWhileUnused, Path::new("F811_24.py"); "F811_24")]
|
||||||
#[test_case(Rule::UndefinedName, Path::new("F821_0.py"); "F821_0")]
|
#[test_case(Rule::UndefinedName, Path::new("F821_0.py"); "F821_0")]
|
||||||
#[test_case(Rule::UndefinedName, Path::new("F821_1.py"); "F821_1")]
|
#[test_case(Rule::UndefinedName, Path::new("F821_1.py"); "F821_1")]
|
||||||
#[test_case(Rule::UndefinedName, Path::new("F821_2.py"); "F821_2")]
|
#[test_case(Rule::UndefinedName, Path::new("F821_2.py"); "F821_2")]
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
---
|
||||||
|
source: crates/ruff/src/rules/pyflakes/mod.rs
|
||||||
|
---
|
||||||
|
F811_23.py:4:8: F811 Redefinition of unused `foo` from line 3
|
||||||
|
|
|
||||||
|
4 | import foo as foo
|
||||||
|
5 | import bar as foo
|
||||||
|
| ^^^^^^^^^^ F811
|
||||||
|
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
---
|
||||||
|
source: crates/ruff/src/rules/pyflakes/mod.rs
|
||||||
|
---
|
||||||
|
|
|
@ -15,17 +15,20 @@ use crate::reference::ReferenceId;
|
||||||
pub struct Binding<'a> {
|
pub struct Binding<'a> {
|
||||||
pub kind: BindingKind<'a>,
|
pub kind: BindingKind<'a>,
|
||||||
pub range: TextRange,
|
pub range: TextRange,
|
||||||
/// 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.
|
||||||
pub source: Option<NodeId>,
|
pub source: Option<NodeId>,
|
||||||
/// The references to the binding.
|
/// The references to the [`Binding`].
|
||||||
pub references: Vec<ReferenceId>,
|
pub references: Vec<ReferenceId>,
|
||||||
/// The exceptions that were handled when the binding was defined.
|
/// The exceptions that were handled when the [`Binding`] was defined.
|
||||||
pub exceptions: Exceptions,
|
pub exceptions: Exceptions,
|
||||||
|
/// Flags for the [`Binding`].
|
||||||
|
pub flags: BindingFlags,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Binding<'a> {
|
impl<'a> Binding<'a> {
|
||||||
|
/// Return `true` if this [`Binding`] is used.
|
||||||
pub fn is_used(&self) -> bool {
|
pub fn is_used(&self) -> bool {
|
||||||
!self.references.is_empty()
|
!self.references.is_empty()
|
||||||
}
|
}
|
||||||
|
@ -35,19 +38,13 @@ impl<'a> Binding<'a> {
|
||||||
self.references.iter().copied()
|
self.references.iter().copied()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const fn is_definition(&self) -> bool {
|
/// Return `true` if this [`Binding`] represents an explicit re-export
|
||||||
matches!(
|
/// (e.g., `import FastAPI as FastAPI`).
|
||||||
self.kind,
|
pub const fn is_explicit_export(&self) -> bool {
|
||||||
BindingKind::ClassDefinition
|
self.flags.contains(BindingFlags::EXPLICIT_EXPORT)
|
||||||
| BindingKind::FunctionDefinition
|
|
||||||
| BindingKind::Builtin
|
|
||||||
| BindingKind::FutureImportation
|
|
||||||
| BindingKind::Importation(..)
|
|
||||||
| BindingKind::FromImportation(..)
|
|
||||||
| BindingKind::SubmoduleImportation(..)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Return `true` if this binding redefines the given binding.
|
||||||
pub fn redefines(&self, existing: &'a Binding) -> bool {
|
pub fn redefines(&self, existing: &'a Binding) -> bool {
|
||||||
match &self.kind {
|
match &self.kind {
|
||||||
BindingKind::Importation(Importation { full_name, .. }) => {
|
BindingKind::Importation(Importation { full_name, .. }) => {
|
||||||
|
@ -97,7 +94,15 @@ impl<'a> Binding<'a> {
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
existing.is_definition()
|
matches!(
|
||||||
|
existing.kind,
|
||||||
|
BindingKind::ClassDefinition
|
||||||
|
| BindingKind::FunctionDefinition
|
||||||
|
| BindingKind::Builtin
|
||||||
|
| BindingKind::Importation(..)
|
||||||
|
| BindingKind::FromImportation(..)
|
||||||
|
| BindingKind::SubmoduleImportation(..)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the appropriate visual range for highlighting this binding.
|
/// Returns the appropriate visual range for highlighting this binding.
|
||||||
|
@ -113,6 +118,20 @@ impl<'a> Binding<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bitflags! {
|
||||||
|
/// Flags on a [`Binding`].
|
||||||
|
#[derive(Debug, Default, Copy, Clone, Eq, PartialEq)]
|
||||||
|
pub struct BindingFlags: u8 {
|
||||||
|
/// The binding represents an explicit re-export.
|
||||||
|
///
|
||||||
|
/// For example, the binding could be `FastAPI` in:
|
||||||
|
/// ```python
|
||||||
|
/// import FastAPI as FastAPI
|
||||||
|
/// ```
|
||||||
|
const EXPLICIT_EXPORT = 1 << 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// ID uniquely identifying a [Binding] in a program.
|
/// ID uniquely identifying a [Binding] in a program.
|
||||||
///
|
///
|
||||||
/// Using a `u32` to identify [Binding]s should is sufficient because Ruff only supports documents with a
|
/// Using a `u32` to identify [Binding]s should is sufficient because Ruff only supports documents with a
|
||||||
|
|
|
@ -34,10 +34,6 @@ pub enum ReferenceContext {
|
||||||
Runtime,
|
Runtime,
|
||||||
/// The reference occurs in a typing-only context.
|
/// The reference occurs in a typing-only context.
|
||||||
Typing,
|
Typing,
|
||||||
/// The reference occurs in a synthetic context, used for `__future__` imports, explicit
|
|
||||||
/// re-exports, and other bindings that should be considered used even if they're never
|
|
||||||
/// "referenced".
|
|
||||||
Synthetic,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Id uniquely identifying a read reference in a program.
|
/// Id uniquely identifying a read reference in a program.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue