Add a convenience method to check if a name is bound (#4718)

This commit is contained in:
Charlie Marsh 2023-05-29 21:52:41 -04:00 committed by GitHub
parent 1846d90bbd
commit 80fa3f2bfa
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 16 additions and 18 deletions

View file

@ -150,10 +150,7 @@ impl<'a> Importer<'a> {
// Case 1: `from functools import lru_cache` is in scope, and we're trying to reference // Case 1: `from functools import lru_cache` is in scope, and we're trying to reference
// `functools.cache`; thus, we add `cache` to the import, and return `"cache"` as the // `functools.cache`; thus, we add `cache` to the import, and return `"cache"` as the
// bound name. // bound name.
if semantic_model if semantic_model.is_unbound(member) {
.find_binding(member)
.map_or(true, |binding| binding.kind.is_builtin())
{
let import_edit = self.add_member(stmt, member)?; let import_edit = self.add_member(stmt, member)?;
Ok((import_edit, member.to_string())) Ok((import_edit, member.to_string()))
} else { } else {
@ -162,10 +159,7 @@ impl<'a> Importer<'a> {
} else { } else {
// Case 2: No `functools` import is in scope; thus, we add `import functools`, and // Case 2: No `functools` import is in scope; thus, we add `import functools`, and
// return `"functools.cache"` as the bound name. // return `"functools.cache"` as the bound name.
if semantic_model if semantic_model.is_unbound(module) {
.find_binding(module)
.map_or(true, |binding| binding.kind.is_builtin())
{
let import_edit = self.add_import(&AnyImport::Import(Import::module(module)), at); let import_edit = self.add_import(&AnyImport::Import(Import::module(module)), at);
Ok((import_edit, format!("{module}.{member}"))) Ok((import_edit, format!("{module}.{member}")))
} else { } else {

View file

@ -29,17 +29,15 @@ pub(crate) fn open_alias(checker: &mut Checker, expr: &Expr, func: &Expr) {
.resolve_call_path(func) .resolve_call_path(func)
.map_or(false, |call_path| call_path.as_slice() == ["io", "open"]) .map_or(false, |call_path| call_path.as_slice() == ["io", "open"])
{ {
let fixable = checker
.semantic_model()
.find_binding("open")
.map_or(true, |binding| binding.kind.is_builtin());
let mut diagnostic = Diagnostic::new(OpenAlias, expr.range()); let mut diagnostic = Diagnostic::new(OpenAlias, expr.range());
if fixable && checker.patch(diagnostic.kind.rule()) { if checker.patch(diagnostic.kind.rule()) {
#[allow(deprecated)] if checker.semantic_model().is_unbound("open") {
diagnostic.set_fix(Fix::unspecified(Edit::range_replacement( #[allow(deprecated)]
"open".to_string(), diagnostic.set_fix(Fix::unspecified(Edit::range_replacement(
func.range(), "open".to_string(),
))); func.range(),
)));
}
} }
checker.diagnostics.push(diagnostic); checker.diagnostics.push(diagnostic);
} }

View file

@ -123,6 +123,12 @@ impl<'a> SemanticModel<'a> {
.map_or(false, |binding| binding.kind.is_builtin()) .map_or(false, |binding| binding.kind.is_builtin())
} }
/// Return `true` if `member` is unbound.
pub fn is_unbound(&self, member: &str) -> bool {
self.find_binding(member)
.map_or(true, |binding| binding.kind.is_builtin())
}
/// Resolve a reference to the given symbol. /// Resolve a reference to the given symbol.
pub fn resolve_reference(&mut self, symbol: &str, range: TextRange) -> ResolvedReference { pub fn resolve_reference(&mut self, symbol: &str, range: TextRange) -> ResolvedReference {
// PEP 563 indicates that if a forward reference can be resolved in the module scope, we // PEP 563 indicates that if a forward reference can be resolved in the module scope, we