use bitflags::bitflags; use ruff_text_size::TextRange; use std::ops::Deref; use ruff_index::{newtype_index, IndexSlice, IndexVec}; use ruff_python_ast::source_code::Locator; use crate::context::ExecutionContext; use crate::scope::ScopeId; use crate::Exceptions; /// A resolved read reference to a name in a program. #[derive(Debug, Clone)] pub struct ResolvedReference { /// The scope in which the reference is defined. scope_id: ScopeId, /// The range of the reference in the source code. range: TextRange, /// The context in which the reference occurs. context: ExecutionContext, } impl ResolvedReference { pub const fn scope_id(&self) -> ScopeId { self.scope_id } pub const fn range(&self) -> TextRange { self.range } pub const fn context(&self) -> ExecutionContext { self.context } } /// Id uniquely identifying a read reference in a program. #[newtype_index] pub struct ResolvedReferenceId; /// The references of a program indexed by [`ResolvedReferenceId`]. #[derive(Debug, Default)] pub(crate) struct ResolvedReferences(IndexVec); impl ResolvedReferences { /// Pushes a new [`ResolvedReference`] and returns its [`ResolvedReferenceId`]. pub(crate) fn push( &mut self, scope_id: ScopeId, range: TextRange, context: ExecutionContext, ) -> ResolvedReferenceId { self.0.push(ResolvedReference { scope_id, range, context, }) } } impl Deref for ResolvedReferences { type Target = IndexSlice; fn deref(&self) -> &Self::Target { &self.0 } } /// An unresolved read reference to a name in a program. #[derive(Debug, Clone)] pub struct UnresolvedReference { /// The range of the reference in the source code. range: TextRange, /// The set of exceptions that were handled when resolution was attempted. exceptions: Exceptions, /// Flags indicating the context in which the reference occurs. flags: UnresolvedReferenceFlags, } impl UnresolvedReference { pub const fn range(&self) -> TextRange { self.range } pub const fn exceptions(&self) -> Exceptions { self.exceptions } pub const fn wildcard_import(&self) -> bool { self.flags .contains(UnresolvedReferenceFlags::WILDCARD_IMPORT) } pub fn name<'a>(&self, locator: &Locator<'a>) -> &'a str { locator.slice(self.range) } } bitflags! { #[derive(Copy, Clone, Debug)] pub struct UnresolvedReferenceFlags: u8 { /// The unresolved reference appeared in a context that includes a wildcard import. const WILDCARD_IMPORT = 1 << 0; } } #[derive(Debug, Default)] pub(crate) struct UnresolvedReferences(Vec); impl UnresolvedReferences { /// Pushes a new [`UnresolvedReference`]. pub(crate) fn push( &mut self, range: TextRange, exceptions: Exceptions, flags: UnresolvedReferenceFlags, ) { self.0.push(UnresolvedReference { range, exceptions, flags, }); } } impl Deref for UnresolvedReferences { type Target = Vec; fn deref(&self) -> &Self::Target { &self.0 } }