mirror of
https://github.com/astral-sh/ruff.git
synced 2025-11-02 12:58:27 +00:00
[ty] Add infrastructure for AST garbage collection (#18445)
## Summary https://github.com/astral-sh/ty/issues/214 will require a couple invasive changes that I would like to get merged even before garbage collection is fully implemented (to avoid rebasing): - `ParsedModule` can no longer be dereferenced directly. Instead you need to load a `ParsedModuleRef` to access the AST, which requires a reference to the salsa database (as it may require re-parsing the AST if it was collected). - `AstNodeRef` can only be dereferenced with the `node` method, which takes a reference to the `ParsedModuleRef`. This allows us to encode the fact that ASTs do not live as long as the database and may be collected as soon a given instance of a `ParsedModuleRef` is dropped. There are a number of places where we currently merge the `'db` and `'ast` lifetimes, so this requires giving some types/functions two separate lifetime parameters.
This commit is contained in:
parent
55100209c7
commit
8531f4b3ca
33 changed files with 886 additions and 689 deletions
|
|
@ -5,7 +5,7 @@ use except_handlers::TryNodeContextStackManager;
|
|||
use rustc_hash::{FxHashMap, FxHashSet};
|
||||
|
||||
use ruff_db::files::File;
|
||||
use ruff_db::parsed::ParsedModule;
|
||||
use ruff_db::parsed::ParsedModuleRef;
|
||||
use ruff_db::source::{SourceText, source_text};
|
||||
use ruff_index::IndexVec;
|
||||
use ruff_python_ast::name::Name;
|
||||
|
|
@ -69,20 +69,20 @@ struct ScopeInfo {
|
|||
current_loop: Option<Loop>,
|
||||
}
|
||||
|
||||
pub(super) struct SemanticIndexBuilder<'db> {
|
||||
pub(super) struct SemanticIndexBuilder<'db, 'ast> {
|
||||
// Builder state
|
||||
db: &'db dyn Db,
|
||||
file: File,
|
||||
source_type: PySourceType,
|
||||
module: &'db ParsedModule,
|
||||
module: &'ast ParsedModuleRef,
|
||||
scope_stack: Vec<ScopeInfo>,
|
||||
/// The assignments we're currently visiting, with
|
||||
/// the most recent visit at the end of the Vec
|
||||
current_assignments: Vec<CurrentAssignment<'db>>,
|
||||
current_assignments: Vec<CurrentAssignment<'ast, 'db>>,
|
||||
/// The match case we're currently visiting.
|
||||
current_match_case: Option<CurrentMatchCase<'db>>,
|
||||
current_match_case: Option<CurrentMatchCase<'ast>>,
|
||||
/// The name of the first function parameter of the innermost function that we're currently visiting.
|
||||
current_first_parameter_name: Option<&'db str>,
|
||||
current_first_parameter_name: Option<&'ast str>,
|
||||
|
||||
/// Per-scope contexts regarding nested `try`/`except` statements
|
||||
try_node_context_stack_manager: TryNodeContextStackManager,
|
||||
|
|
@ -116,13 +116,13 @@ pub(super) struct SemanticIndexBuilder<'db> {
|
|||
semantic_syntax_errors: RefCell<Vec<SemanticSyntaxError>>,
|
||||
}
|
||||
|
||||
impl<'db> SemanticIndexBuilder<'db> {
|
||||
pub(super) fn new(db: &'db dyn Db, file: File, parsed: &'db ParsedModule) -> Self {
|
||||
impl<'db, 'ast> SemanticIndexBuilder<'db, 'ast> {
|
||||
pub(super) fn new(db: &'db dyn Db, file: File, module_ref: &'ast ParsedModuleRef) -> Self {
|
||||
let mut builder = Self {
|
||||
db,
|
||||
file,
|
||||
source_type: file.source_type(db.upcast()),
|
||||
module: parsed,
|
||||
module: module_ref,
|
||||
scope_stack: Vec::new(),
|
||||
current_assignments: vec![],
|
||||
current_match_case: None,
|
||||
|
|
@ -423,7 +423,7 @@ impl<'db> SemanticIndexBuilder<'db> {
|
|||
fn add_definition(
|
||||
&mut self,
|
||||
place: ScopedPlaceId,
|
||||
definition_node: impl Into<DefinitionNodeRef<'db>> + std::fmt::Debug + Copy,
|
||||
definition_node: impl Into<DefinitionNodeRef<'ast, 'db>> + std::fmt::Debug + Copy,
|
||||
) -> Definition<'db> {
|
||||
let (definition, num_definitions) = self.push_additional_definition(place, definition_node);
|
||||
debug_assert_eq!(
|
||||
|
|
@ -463,16 +463,18 @@ impl<'db> SemanticIndexBuilder<'db> {
|
|||
fn push_additional_definition(
|
||||
&mut self,
|
||||
place: ScopedPlaceId,
|
||||
definition_node: impl Into<DefinitionNodeRef<'db>>,
|
||||
definition_node: impl Into<DefinitionNodeRef<'ast, 'db>>,
|
||||
) -> (Definition<'db>, usize) {
|
||||
let definition_node: DefinitionNodeRef<'_> = definition_node.into();
|
||||
let definition_node: DefinitionNodeRef<'ast, 'db> = definition_node.into();
|
||||
|
||||
#[expect(unsafe_code)]
|
||||
// SAFETY: `definition_node` is guaranteed to be a child of `self.module`
|
||||
let kind = unsafe { definition_node.into_owned(self.module.clone()) };
|
||||
let category = kind.category(self.source_type.is_stub());
|
||||
|
||||
let category = kind.category(self.source_type.is_stub(), self.module);
|
||||
let is_reexported = kind.is_reexported();
|
||||
|
||||
let definition = Definition::new(
|
||||
let definition: Definition<'db> = Definition::new(
|
||||
self.db,
|
||||
self.file,
|
||||
self.current_scope(),
|
||||
|
|
@ -658,7 +660,7 @@ impl<'db> SemanticIndexBuilder<'db> {
|
|||
.record_reachability_constraint(negated_constraint);
|
||||
}
|
||||
|
||||
fn push_assignment(&mut self, assignment: CurrentAssignment<'db>) {
|
||||
fn push_assignment(&mut self, assignment: CurrentAssignment<'ast, 'db>) {
|
||||
self.current_assignments.push(assignment);
|
||||
}
|
||||
|
||||
|
|
@ -667,11 +669,11 @@ impl<'db> SemanticIndexBuilder<'db> {
|
|||
debug_assert!(popped_assignment.is_some());
|
||||
}
|
||||
|
||||
fn current_assignment(&self) -> Option<CurrentAssignment<'db>> {
|
||||
fn current_assignment(&self) -> Option<CurrentAssignment<'ast, 'db>> {
|
||||
self.current_assignments.last().copied()
|
||||
}
|
||||
|
||||
fn current_assignment_mut(&mut self) -> Option<&mut CurrentAssignment<'db>> {
|
||||
fn current_assignment_mut(&mut self) -> Option<&mut CurrentAssignment<'ast, 'db>> {
|
||||
self.current_assignments.last_mut()
|
||||
}
|
||||
|
||||
|
|
@ -792,7 +794,7 @@ impl<'db> SemanticIndexBuilder<'db> {
|
|||
fn with_type_params(
|
||||
&mut self,
|
||||
with_scope: NodeWithScopeRef,
|
||||
type_params: Option<&'db ast::TypeParams>,
|
||||
type_params: Option<&'ast ast::TypeParams>,
|
||||
nested: impl FnOnce(&mut Self) -> FileScopeId,
|
||||
) -> FileScopeId {
|
||||
if let Some(type_params) = type_params {
|
||||
|
|
@ -858,7 +860,7 @@ impl<'db> SemanticIndexBuilder<'db> {
|
|||
fn with_generators_scope(
|
||||
&mut self,
|
||||
scope: NodeWithScopeRef,
|
||||
generators: &'db [ast::Comprehension],
|
||||
generators: &'ast [ast::Comprehension],
|
||||
visit_outer_elt: impl FnOnce(&mut Self),
|
||||
) {
|
||||
let mut generators_iter = generators.iter();
|
||||
|
|
@ -908,7 +910,7 @@ impl<'db> SemanticIndexBuilder<'db> {
|
|||
self.pop_scope();
|
||||
}
|
||||
|
||||
fn declare_parameters(&mut self, parameters: &'db ast::Parameters) {
|
||||
fn declare_parameters(&mut self, parameters: &'ast ast::Parameters) {
|
||||
for parameter in parameters.iter_non_variadic_params() {
|
||||
self.declare_parameter(parameter);
|
||||
}
|
||||
|
|
@ -925,7 +927,7 @@ impl<'db> SemanticIndexBuilder<'db> {
|
|||
}
|
||||
}
|
||||
|
||||
fn declare_parameter(&mut self, parameter: &'db ast::ParameterWithDefault) {
|
||||
fn declare_parameter(&mut self, parameter: &'ast ast::ParameterWithDefault) {
|
||||
let symbol = self.add_symbol(parameter.name().id().clone());
|
||||
|
||||
let definition = self.add_definition(symbol, parameter);
|
||||
|
|
@ -946,8 +948,8 @@ impl<'db> SemanticIndexBuilder<'db> {
|
|||
/// for statements, etc.
|
||||
fn add_unpackable_assignment(
|
||||
&mut self,
|
||||
unpackable: &Unpackable<'db>,
|
||||
target: &'db ast::Expr,
|
||||
unpackable: &Unpackable<'ast>,
|
||||
target: &'ast ast::Expr,
|
||||
value: Expression<'db>,
|
||||
) {
|
||||
// We only handle assignments to names and unpackings here, other targets like
|
||||
|
|
@ -1010,8 +1012,7 @@ impl<'db> SemanticIndexBuilder<'db> {
|
|||
}
|
||||
|
||||
pub(super) fn build(mut self) -> SemanticIndex<'db> {
|
||||
let module = self.module;
|
||||
self.visit_body(module.suite());
|
||||
self.visit_body(self.module.suite());
|
||||
|
||||
// Pop the root scope
|
||||
self.pop_scope();
|
||||
|
|
@ -1081,10 +1082,7 @@ impl<'db> SemanticIndexBuilder<'db> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'db, 'ast> Visitor<'ast> for SemanticIndexBuilder<'db>
|
||||
where
|
||||
'ast: 'db,
|
||||
{
|
||||
impl<'ast> Visitor<'ast> for SemanticIndexBuilder<'_, 'ast> {
|
||||
fn visit_stmt(&mut self, stmt: &'ast ast::Stmt) {
|
||||
self.with_semantic_checker(|semantic, context| semantic.visit_stmt(stmt, context));
|
||||
|
||||
|
|
@ -2299,7 +2297,7 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
impl SemanticSyntaxContext for SemanticIndexBuilder<'_> {
|
||||
impl SemanticSyntaxContext for SemanticIndexBuilder<'_, '_> {
|
||||
fn future_annotations_or_stub(&self) -> bool {
|
||||
self.has_future_annotations
|
||||
}
|
||||
|
|
@ -2324,7 +2322,7 @@ impl SemanticSyntaxContext for SemanticIndexBuilder<'_> {
|
|||
match scope.kind() {
|
||||
ScopeKind::Class | ScopeKind::Lambda => return false,
|
||||
ScopeKind::Function => {
|
||||
return scope.node().expect_function().is_async;
|
||||
return scope.node().expect_function(self.module).is_async;
|
||||
}
|
||||
ScopeKind::Comprehension
|
||||
| ScopeKind::Module
|
||||
|
|
@ -2366,9 +2364,9 @@ impl SemanticSyntaxContext for SemanticIndexBuilder<'_> {
|
|||
for scope_info in self.scope_stack.iter().rev() {
|
||||
let scope = &self.scopes[scope_info.file_scope_id];
|
||||
let generators = match scope.node() {
|
||||
NodeWithScopeKind::ListComprehension(node) => &node.generators,
|
||||
NodeWithScopeKind::SetComprehension(node) => &node.generators,
|
||||
NodeWithScopeKind::DictComprehension(node) => &node.generators,
|
||||
NodeWithScopeKind::ListComprehension(node) => &node.node(self.module).generators,
|
||||
NodeWithScopeKind::SetComprehension(node) => &node.node(self.module).generators,
|
||||
NodeWithScopeKind::DictComprehension(node) => &node.node(self.module).generators,
|
||||
_ => continue,
|
||||
};
|
||||
if generators
|
||||
|
|
@ -2409,31 +2407,31 @@ impl SemanticSyntaxContext for SemanticIndexBuilder<'_> {
|
|||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq)]
|
||||
enum CurrentAssignment<'a> {
|
||||
enum CurrentAssignment<'ast, 'db> {
|
||||
Assign {
|
||||
node: &'a ast::StmtAssign,
|
||||
unpack: Option<(UnpackPosition, Unpack<'a>)>,
|
||||
node: &'ast ast::StmtAssign,
|
||||
unpack: Option<(UnpackPosition, Unpack<'db>)>,
|
||||
},
|
||||
AnnAssign(&'a ast::StmtAnnAssign),
|
||||
AugAssign(&'a ast::StmtAugAssign),
|
||||
AnnAssign(&'ast ast::StmtAnnAssign),
|
||||
AugAssign(&'ast ast::StmtAugAssign),
|
||||
For {
|
||||
node: &'a ast::StmtFor,
|
||||
unpack: Option<(UnpackPosition, Unpack<'a>)>,
|
||||
node: &'ast ast::StmtFor,
|
||||
unpack: Option<(UnpackPosition, Unpack<'db>)>,
|
||||
},
|
||||
Named(&'a ast::ExprNamed),
|
||||
Named(&'ast ast::ExprNamed),
|
||||
Comprehension {
|
||||
node: &'a ast::Comprehension,
|
||||
node: &'ast ast::Comprehension,
|
||||
first: bool,
|
||||
unpack: Option<(UnpackPosition, Unpack<'a>)>,
|
||||
unpack: Option<(UnpackPosition, Unpack<'db>)>,
|
||||
},
|
||||
WithItem {
|
||||
item: &'a ast::WithItem,
|
||||
item: &'ast ast::WithItem,
|
||||
is_async: bool,
|
||||
unpack: Option<(UnpackPosition, Unpack<'a>)>,
|
||||
unpack: Option<(UnpackPosition, Unpack<'db>)>,
|
||||
},
|
||||
}
|
||||
|
||||
impl CurrentAssignment<'_> {
|
||||
impl CurrentAssignment<'_, '_> {
|
||||
fn unpack_position_mut(&mut self) -> Option<&mut UnpackPosition> {
|
||||
match self {
|
||||
Self::Assign { unpack, .. }
|
||||
|
|
@ -2445,28 +2443,28 @@ impl CurrentAssignment<'_> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a> From<&'a ast::StmtAnnAssign> for CurrentAssignment<'a> {
|
||||
fn from(value: &'a ast::StmtAnnAssign) -> Self {
|
||||
impl<'ast> From<&'ast ast::StmtAnnAssign> for CurrentAssignment<'ast, '_> {
|
||||
fn from(value: &'ast ast::StmtAnnAssign) -> Self {
|
||||
Self::AnnAssign(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<&'a ast::StmtAugAssign> for CurrentAssignment<'a> {
|
||||
fn from(value: &'a ast::StmtAugAssign) -> Self {
|
||||
impl<'ast> From<&'ast ast::StmtAugAssign> for CurrentAssignment<'ast, '_> {
|
||||
fn from(value: &'ast ast::StmtAugAssign) -> Self {
|
||||
Self::AugAssign(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<&'a ast::ExprNamed> for CurrentAssignment<'a> {
|
||||
fn from(value: &'a ast::ExprNamed) -> Self {
|
||||
impl<'ast> From<&'ast ast::ExprNamed> for CurrentAssignment<'ast, '_> {
|
||||
fn from(value: &'ast ast::ExprNamed) -> Self {
|
||||
Self::Named(value)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
struct CurrentMatchCase<'a> {
|
||||
struct CurrentMatchCase<'ast> {
|
||||
/// The pattern that's part of the current match case.
|
||||
pattern: &'a ast::Pattern,
|
||||
pattern: &'ast ast::Pattern,
|
||||
|
||||
/// The index of the sub-pattern that's being currently visited within the pattern.
|
||||
///
|
||||
|
|
@ -2488,20 +2486,20 @@ impl<'a> CurrentMatchCase<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
enum Unpackable<'a> {
|
||||
Assign(&'a ast::StmtAssign),
|
||||
For(&'a ast::StmtFor),
|
||||
enum Unpackable<'ast> {
|
||||
Assign(&'ast ast::StmtAssign),
|
||||
For(&'ast ast::StmtFor),
|
||||
WithItem {
|
||||
item: &'a ast::WithItem,
|
||||
item: &'ast ast::WithItem,
|
||||
is_async: bool,
|
||||
},
|
||||
Comprehension {
|
||||
first: bool,
|
||||
node: &'a ast::Comprehension,
|
||||
node: &'ast ast::Comprehension,
|
||||
},
|
||||
}
|
||||
|
||||
impl<'a> Unpackable<'a> {
|
||||
impl<'ast> Unpackable<'ast> {
|
||||
const fn kind(&self) -> UnpackKind {
|
||||
match self {
|
||||
Unpackable::Assign(_) => UnpackKind::Assign,
|
||||
|
|
@ -2510,7 +2508,10 @@ impl<'a> Unpackable<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
fn as_current_assignment(&self, unpack: Option<Unpack<'a>>) -> CurrentAssignment<'a> {
|
||||
fn as_current_assignment<'db>(
|
||||
&self,
|
||||
unpack: Option<Unpack<'db>>,
|
||||
) -> CurrentAssignment<'ast, 'db> {
|
||||
let unpack = unpack.map(|unpack| (UnpackPosition::First, unpack));
|
||||
match self {
|
||||
Unpackable::Assign(stmt) => CurrentAssignment::Assign { node: stmt, unpack },
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
use std::ops::Deref;
|
||||
|
||||
use ruff_db::files::{File, FileRange};
|
||||
use ruff_db::parsed::ParsedModule;
|
||||
use ruff_db::parsed::ParsedModuleRef;
|
||||
use ruff_python_ast as ast;
|
||||
use ruff_text_size::{Ranged, TextRange};
|
||||
|
||||
|
|
@ -49,12 +49,12 @@ impl<'db> Definition<'db> {
|
|||
self.file_scope(db).to_scope_id(db, self.file(db))
|
||||
}
|
||||
|
||||
pub fn full_range(self, db: &'db dyn Db) -> FileRange {
|
||||
FileRange::new(self.file(db), self.kind(db).full_range())
|
||||
pub fn full_range(self, db: &'db dyn Db, module: &ParsedModuleRef) -> FileRange {
|
||||
FileRange::new(self.file(db), self.kind(db).full_range(module))
|
||||
}
|
||||
|
||||
pub fn focus_range(self, db: &'db dyn Db) -> FileRange {
|
||||
FileRange::new(self.file(db), self.kind(db).target_range())
|
||||
pub fn focus_range(self, db: &'db dyn Db, module: &ParsedModuleRef) -> FileRange {
|
||||
FileRange::new(self.file(db), self.kind(db).target_range(module))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -123,218 +123,218 @@ impl<'db> DefinitionState<'db> {
|
|||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub(crate) enum DefinitionNodeRef<'a> {
|
||||
Import(ImportDefinitionNodeRef<'a>),
|
||||
ImportFrom(ImportFromDefinitionNodeRef<'a>),
|
||||
ImportStar(StarImportDefinitionNodeRef<'a>),
|
||||
For(ForStmtDefinitionNodeRef<'a>),
|
||||
Function(&'a ast::StmtFunctionDef),
|
||||
Class(&'a ast::StmtClassDef),
|
||||
TypeAlias(&'a ast::StmtTypeAlias),
|
||||
NamedExpression(&'a ast::ExprNamed),
|
||||
Assignment(AssignmentDefinitionNodeRef<'a>),
|
||||
AnnotatedAssignment(AnnotatedAssignmentDefinitionNodeRef<'a>),
|
||||
AugmentedAssignment(&'a ast::StmtAugAssign),
|
||||
Comprehension(ComprehensionDefinitionNodeRef<'a>),
|
||||
VariadicPositionalParameter(&'a ast::Parameter),
|
||||
VariadicKeywordParameter(&'a ast::Parameter),
|
||||
Parameter(&'a ast::ParameterWithDefault),
|
||||
WithItem(WithItemDefinitionNodeRef<'a>),
|
||||
MatchPattern(MatchPatternDefinitionNodeRef<'a>),
|
||||
ExceptHandler(ExceptHandlerDefinitionNodeRef<'a>),
|
||||
TypeVar(&'a ast::TypeParamTypeVar),
|
||||
ParamSpec(&'a ast::TypeParamParamSpec),
|
||||
TypeVarTuple(&'a ast::TypeParamTypeVarTuple),
|
||||
pub(crate) enum DefinitionNodeRef<'ast, 'db> {
|
||||
Import(ImportDefinitionNodeRef<'ast>),
|
||||
ImportFrom(ImportFromDefinitionNodeRef<'ast>),
|
||||
ImportStar(StarImportDefinitionNodeRef<'ast>),
|
||||
For(ForStmtDefinitionNodeRef<'ast, 'db>),
|
||||
Function(&'ast ast::StmtFunctionDef),
|
||||
Class(&'ast ast::StmtClassDef),
|
||||
TypeAlias(&'ast ast::StmtTypeAlias),
|
||||
NamedExpression(&'ast ast::ExprNamed),
|
||||
Assignment(AssignmentDefinitionNodeRef<'ast, 'db>),
|
||||
AnnotatedAssignment(AnnotatedAssignmentDefinitionNodeRef<'ast>),
|
||||
AugmentedAssignment(&'ast ast::StmtAugAssign),
|
||||
Comprehension(ComprehensionDefinitionNodeRef<'ast, 'db>),
|
||||
VariadicPositionalParameter(&'ast ast::Parameter),
|
||||
VariadicKeywordParameter(&'ast ast::Parameter),
|
||||
Parameter(&'ast ast::ParameterWithDefault),
|
||||
WithItem(WithItemDefinitionNodeRef<'ast, 'db>),
|
||||
MatchPattern(MatchPatternDefinitionNodeRef<'ast>),
|
||||
ExceptHandler(ExceptHandlerDefinitionNodeRef<'ast>),
|
||||
TypeVar(&'ast ast::TypeParamTypeVar),
|
||||
ParamSpec(&'ast ast::TypeParamParamSpec),
|
||||
TypeVarTuple(&'ast ast::TypeParamTypeVarTuple),
|
||||
}
|
||||
|
||||
impl<'a> From<&'a ast::StmtFunctionDef> for DefinitionNodeRef<'a> {
|
||||
fn from(node: &'a ast::StmtFunctionDef) -> Self {
|
||||
impl<'ast> From<&'ast ast::StmtFunctionDef> for DefinitionNodeRef<'ast, '_> {
|
||||
fn from(node: &'ast ast::StmtFunctionDef) -> Self {
|
||||
Self::Function(node)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<&'a ast::StmtClassDef> for DefinitionNodeRef<'a> {
|
||||
fn from(node: &'a ast::StmtClassDef) -> Self {
|
||||
impl<'ast> From<&'ast ast::StmtClassDef> for DefinitionNodeRef<'ast, '_> {
|
||||
fn from(node: &'ast ast::StmtClassDef) -> Self {
|
||||
Self::Class(node)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<&'a ast::StmtTypeAlias> for DefinitionNodeRef<'a> {
|
||||
fn from(node: &'a ast::StmtTypeAlias) -> Self {
|
||||
impl<'ast> From<&'ast ast::StmtTypeAlias> for DefinitionNodeRef<'ast, '_> {
|
||||
fn from(node: &'ast ast::StmtTypeAlias) -> Self {
|
||||
Self::TypeAlias(node)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<&'a ast::ExprNamed> for DefinitionNodeRef<'a> {
|
||||
fn from(node: &'a ast::ExprNamed) -> Self {
|
||||
impl<'ast> From<&'ast ast::ExprNamed> for DefinitionNodeRef<'ast, '_> {
|
||||
fn from(node: &'ast ast::ExprNamed) -> Self {
|
||||
Self::NamedExpression(node)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<&'a ast::StmtAugAssign> for DefinitionNodeRef<'a> {
|
||||
fn from(node: &'a ast::StmtAugAssign) -> Self {
|
||||
impl<'ast> From<&'ast ast::StmtAugAssign> for DefinitionNodeRef<'ast, '_> {
|
||||
fn from(node: &'ast ast::StmtAugAssign) -> Self {
|
||||
Self::AugmentedAssignment(node)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<&'a ast::TypeParamTypeVar> for DefinitionNodeRef<'a> {
|
||||
fn from(value: &'a ast::TypeParamTypeVar) -> Self {
|
||||
impl<'ast> From<&'ast ast::TypeParamTypeVar> for DefinitionNodeRef<'ast, '_> {
|
||||
fn from(value: &'ast ast::TypeParamTypeVar) -> Self {
|
||||
Self::TypeVar(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<&'a ast::TypeParamParamSpec> for DefinitionNodeRef<'a> {
|
||||
fn from(value: &'a ast::TypeParamParamSpec) -> Self {
|
||||
impl<'ast> From<&'ast ast::TypeParamParamSpec> for DefinitionNodeRef<'ast, '_> {
|
||||
fn from(value: &'ast ast::TypeParamParamSpec) -> Self {
|
||||
Self::ParamSpec(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<&'a ast::TypeParamTypeVarTuple> for DefinitionNodeRef<'a> {
|
||||
fn from(value: &'a ast::TypeParamTypeVarTuple) -> Self {
|
||||
impl<'ast> From<&'ast ast::TypeParamTypeVarTuple> for DefinitionNodeRef<'ast, '_> {
|
||||
fn from(value: &'ast ast::TypeParamTypeVarTuple) -> Self {
|
||||
Self::TypeVarTuple(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<ImportDefinitionNodeRef<'a>> for DefinitionNodeRef<'a> {
|
||||
fn from(node_ref: ImportDefinitionNodeRef<'a>) -> Self {
|
||||
impl<'ast> From<ImportDefinitionNodeRef<'ast>> for DefinitionNodeRef<'ast, '_> {
|
||||
fn from(node_ref: ImportDefinitionNodeRef<'ast>) -> Self {
|
||||
Self::Import(node_ref)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<ImportFromDefinitionNodeRef<'a>> for DefinitionNodeRef<'a> {
|
||||
fn from(node_ref: ImportFromDefinitionNodeRef<'a>) -> Self {
|
||||
impl<'ast> From<ImportFromDefinitionNodeRef<'ast>> for DefinitionNodeRef<'ast, '_> {
|
||||
fn from(node_ref: ImportFromDefinitionNodeRef<'ast>) -> Self {
|
||||
Self::ImportFrom(node_ref)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<ForStmtDefinitionNodeRef<'a>> for DefinitionNodeRef<'a> {
|
||||
fn from(value: ForStmtDefinitionNodeRef<'a>) -> Self {
|
||||
impl<'ast, 'db> From<ForStmtDefinitionNodeRef<'ast, 'db>> for DefinitionNodeRef<'ast, 'db> {
|
||||
fn from(value: ForStmtDefinitionNodeRef<'ast, 'db>) -> Self {
|
||||
Self::For(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<AssignmentDefinitionNodeRef<'a>> for DefinitionNodeRef<'a> {
|
||||
fn from(node_ref: AssignmentDefinitionNodeRef<'a>) -> Self {
|
||||
impl<'ast, 'db> From<AssignmentDefinitionNodeRef<'ast, 'db>> for DefinitionNodeRef<'ast, 'db> {
|
||||
fn from(node_ref: AssignmentDefinitionNodeRef<'ast, 'db>) -> Self {
|
||||
Self::Assignment(node_ref)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<AnnotatedAssignmentDefinitionNodeRef<'a>> for DefinitionNodeRef<'a> {
|
||||
fn from(node_ref: AnnotatedAssignmentDefinitionNodeRef<'a>) -> Self {
|
||||
impl<'ast> From<AnnotatedAssignmentDefinitionNodeRef<'ast>> for DefinitionNodeRef<'ast, '_> {
|
||||
fn from(node_ref: AnnotatedAssignmentDefinitionNodeRef<'ast>) -> Self {
|
||||
Self::AnnotatedAssignment(node_ref)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<WithItemDefinitionNodeRef<'a>> for DefinitionNodeRef<'a> {
|
||||
fn from(node_ref: WithItemDefinitionNodeRef<'a>) -> Self {
|
||||
impl<'ast, 'db> From<WithItemDefinitionNodeRef<'ast, 'db>> for DefinitionNodeRef<'ast, 'db> {
|
||||
fn from(node_ref: WithItemDefinitionNodeRef<'ast, 'db>) -> Self {
|
||||
Self::WithItem(node_ref)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<ComprehensionDefinitionNodeRef<'a>> for DefinitionNodeRef<'a> {
|
||||
fn from(node: ComprehensionDefinitionNodeRef<'a>) -> Self {
|
||||
impl<'ast, 'db> From<ComprehensionDefinitionNodeRef<'ast, 'db>> for DefinitionNodeRef<'ast, 'db> {
|
||||
fn from(node: ComprehensionDefinitionNodeRef<'ast, 'db>) -> Self {
|
||||
Self::Comprehension(node)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<&'a ast::ParameterWithDefault> for DefinitionNodeRef<'a> {
|
||||
fn from(node: &'a ast::ParameterWithDefault) -> Self {
|
||||
impl<'ast> From<&'ast ast::ParameterWithDefault> for DefinitionNodeRef<'ast, '_> {
|
||||
fn from(node: &'ast ast::ParameterWithDefault) -> Self {
|
||||
Self::Parameter(node)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<MatchPatternDefinitionNodeRef<'a>> for DefinitionNodeRef<'a> {
|
||||
fn from(node: MatchPatternDefinitionNodeRef<'a>) -> Self {
|
||||
impl<'ast> From<MatchPatternDefinitionNodeRef<'ast>> for DefinitionNodeRef<'ast, '_> {
|
||||
fn from(node: MatchPatternDefinitionNodeRef<'ast>) -> Self {
|
||||
Self::MatchPattern(node)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<StarImportDefinitionNodeRef<'a>> for DefinitionNodeRef<'a> {
|
||||
fn from(node: StarImportDefinitionNodeRef<'a>) -> Self {
|
||||
impl<'ast> From<StarImportDefinitionNodeRef<'ast>> for DefinitionNodeRef<'ast, '_> {
|
||||
fn from(node: StarImportDefinitionNodeRef<'ast>) -> Self {
|
||||
Self::ImportStar(node)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub(crate) struct ImportDefinitionNodeRef<'a> {
|
||||
pub(crate) node: &'a ast::StmtImport,
|
||||
pub(crate) struct ImportDefinitionNodeRef<'ast> {
|
||||
pub(crate) node: &'ast ast::StmtImport,
|
||||
pub(crate) alias_index: usize,
|
||||
pub(crate) is_reexported: bool,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub(crate) struct StarImportDefinitionNodeRef<'a> {
|
||||
pub(crate) node: &'a ast::StmtImportFrom,
|
||||
pub(crate) struct StarImportDefinitionNodeRef<'ast> {
|
||||
pub(crate) node: &'ast ast::StmtImportFrom,
|
||||
pub(crate) place_id: ScopedPlaceId,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub(crate) struct ImportFromDefinitionNodeRef<'a> {
|
||||
pub(crate) node: &'a ast::StmtImportFrom,
|
||||
pub(crate) struct ImportFromDefinitionNodeRef<'ast> {
|
||||
pub(crate) node: &'ast ast::StmtImportFrom,
|
||||
pub(crate) alias_index: usize,
|
||||
pub(crate) is_reexported: bool,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub(crate) struct AssignmentDefinitionNodeRef<'a> {
|
||||
pub(crate) unpack: Option<(UnpackPosition, Unpack<'a>)>,
|
||||
pub(crate) value: &'a ast::Expr,
|
||||
pub(crate) target: &'a ast::Expr,
|
||||
pub(crate) struct AssignmentDefinitionNodeRef<'ast, 'db> {
|
||||
pub(crate) unpack: Option<(UnpackPosition, Unpack<'db>)>,
|
||||
pub(crate) value: &'ast ast::Expr,
|
||||
pub(crate) target: &'ast ast::Expr,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub(crate) struct AnnotatedAssignmentDefinitionNodeRef<'a> {
|
||||
pub(crate) node: &'a ast::StmtAnnAssign,
|
||||
pub(crate) annotation: &'a ast::Expr,
|
||||
pub(crate) value: Option<&'a ast::Expr>,
|
||||
pub(crate) target: &'a ast::Expr,
|
||||
pub(crate) struct AnnotatedAssignmentDefinitionNodeRef<'ast> {
|
||||
pub(crate) node: &'ast ast::StmtAnnAssign,
|
||||
pub(crate) annotation: &'ast ast::Expr,
|
||||
pub(crate) value: Option<&'ast ast::Expr>,
|
||||
pub(crate) target: &'ast ast::Expr,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub(crate) struct WithItemDefinitionNodeRef<'a> {
|
||||
pub(crate) unpack: Option<(UnpackPosition, Unpack<'a>)>,
|
||||
pub(crate) context_expr: &'a ast::Expr,
|
||||
pub(crate) target: &'a ast::Expr,
|
||||
pub(crate) struct WithItemDefinitionNodeRef<'ast, 'db> {
|
||||
pub(crate) unpack: Option<(UnpackPosition, Unpack<'db>)>,
|
||||
pub(crate) context_expr: &'ast ast::Expr,
|
||||
pub(crate) target: &'ast ast::Expr,
|
||||
pub(crate) is_async: bool,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub(crate) struct ForStmtDefinitionNodeRef<'a> {
|
||||
pub(crate) unpack: Option<(UnpackPosition, Unpack<'a>)>,
|
||||
pub(crate) iterable: &'a ast::Expr,
|
||||
pub(crate) target: &'a ast::Expr,
|
||||
pub(crate) struct ForStmtDefinitionNodeRef<'ast, 'db> {
|
||||
pub(crate) unpack: Option<(UnpackPosition, Unpack<'db>)>,
|
||||
pub(crate) iterable: &'ast ast::Expr,
|
||||
pub(crate) target: &'ast ast::Expr,
|
||||
pub(crate) is_async: bool,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub(crate) struct ExceptHandlerDefinitionNodeRef<'a> {
|
||||
pub(crate) handler: &'a ast::ExceptHandlerExceptHandler,
|
||||
pub(crate) struct ExceptHandlerDefinitionNodeRef<'ast> {
|
||||
pub(crate) handler: &'ast ast::ExceptHandlerExceptHandler,
|
||||
pub(crate) is_star: bool,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub(crate) struct ComprehensionDefinitionNodeRef<'a> {
|
||||
pub(crate) unpack: Option<(UnpackPosition, Unpack<'a>)>,
|
||||
pub(crate) iterable: &'a ast::Expr,
|
||||
pub(crate) target: &'a ast::Expr,
|
||||
pub(crate) struct ComprehensionDefinitionNodeRef<'ast, 'db> {
|
||||
pub(crate) unpack: Option<(UnpackPosition, Unpack<'db>)>,
|
||||
pub(crate) iterable: &'ast ast::Expr,
|
||||
pub(crate) target: &'ast ast::Expr,
|
||||
pub(crate) first: bool,
|
||||
pub(crate) is_async: bool,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub(crate) struct MatchPatternDefinitionNodeRef<'a> {
|
||||
pub(crate) struct MatchPatternDefinitionNodeRef<'ast> {
|
||||
/// The outermost pattern node in which the identifier being defined occurs.
|
||||
pub(crate) pattern: &'a ast::Pattern,
|
||||
pub(crate) pattern: &'ast ast::Pattern,
|
||||
/// The identifier being defined.
|
||||
pub(crate) identifier: &'a ast::Identifier,
|
||||
pub(crate) identifier: &'ast ast::Identifier,
|
||||
/// The index of the identifier in the pattern when visiting the `pattern` node in evaluation
|
||||
/// order.
|
||||
pub(crate) index: u32,
|
||||
}
|
||||
|
||||
impl<'db> DefinitionNodeRef<'db> {
|
||||
impl<'db> DefinitionNodeRef<'_, 'db> {
|
||||
#[expect(unsafe_code)]
|
||||
pub(super) unsafe fn into_owned(self, parsed: ParsedModule) -> DefinitionKind<'db> {
|
||||
pub(super) unsafe fn into_owned(self, parsed: ParsedModuleRef) -> DefinitionKind<'db> {
|
||||
match self {
|
||||
DefinitionNodeRef::Import(ImportDefinitionNodeRef {
|
||||
node,
|
||||
|
|
@ -626,60 +626,74 @@ impl DefinitionKind<'_> {
|
|||
///
|
||||
/// A definition target would mainly be the node representing the place being defined i.e.,
|
||||
/// [`ast::ExprName`], [`ast::Identifier`], [`ast::ExprAttribute`] or [`ast::ExprSubscript`] but could also be other nodes.
|
||||
pub(crate) fn target_range(&self) -> TextRange {
|
||||
pub(crate) fn target_range(&self, module: &ParsedModuleRef) -> TextRange {
|
||||
match self {
|
||||
DefinitionKind::Import(import) => import.alias().range(),
|
||||
DefinitionKind::ImportFrom(import) => import.alias().range(),
|
||||
DefinitionKind::StarImport(import) => import.alias().range(),
|
||||
DefinitionKind::Function(function) => function.name.range(),
|
||||
DefinitionKind::Class(class) => class.name.range(),
|
||||
DefinitionKind::TypeAlias(type_alias) => type_alias.name.range(),
|
||||
DefinitionKind::NamedExpression(named) => named.target.range(),
|
||||
DefinitionKind::Assignment(assignment) => assignment.target.range(),
|
||||
DefinitionKind::AnnotatedAssignment(assign) => assign.target.range(),
|
||||
DefinitionKind::AugmentedAssignment(aug_assign) => aug_assign.target.range(),
|
||||
DefinitionKind::For(for_stmt) => for_stmt.target.range(),
|
||||
DefinitionKind::Comprehension(comp) => comp.target().range(),
|
||||
DefinitionKind::VariadicPositionalParameter(parameter) => parameter.name.range(),
|
||||
DefinitionKind::VariadicKeywordParameter(parameter) => parameter.name.range(),
|
||||
DefinitionKind::Parameter(parameter) => parameter.parameter.name.range(),
|
||||
DefinitionKind::WithItem(with_item) => with_item.target.range(),
|
||||
DefinitionKind::MatchPattern(match_pattern) => match_pattern.identifier.range(),
|
||||
DefinitionKind::ExceptHandler(handler) => handler.node().range(),
|
||||
DefinitionKind::TypeVar(type_var) => type_var.name.range(),
|
||||
DefinitionKind::ParamSpec(param_spec) => param_spec.name.range(),
|
||||
DefinitionKind::TypeVarTuple(type_var_tuple) => type_var_tuple.name.range(),
|
||||
DefinitionKind::Import(import) => import.alias(module).range(),
|
||||
DefinitionKind::ImportFrom(import) => import.alias(module).range(),
|
||||
DefinitionKind::StarImport(import) => import.alias(module).range(),
|
||||
DefinitionKind::Function(function) => function.node(module).name.range(),
|
||||
DefinitionKind::Class(class) => class.node(module).name.range(),
|
||||
DefinitionKind::TypeAlias(type_alias) => type_alias.node(module).name.range(),
|
||||
DefinitionKind::NamedExpression(named) => named.node(module).target.range(),
|
||||
DefinitionKind::Assignment(assignment) => assignment.target.node(module).range(),
|
||||
DefinitionKind::AnnotatedAssignment(assign) => assign.target.node(module).range(),
|
||||
DefinitionKind::AugmentedAssignment(aug_assign) => {
|
||||
aug_assign.node(module).target.range()
|
||||
}
|
||||
DefinitionKind::For(for_stmt) => for_stmt.target.node(module).range(),
|
||||
DefinitionKind::Comprehension(comp) => comp.target(module).range(),
|
||||
DefinitionKind::VariadicPositionalParameter(parameter) => {
|
||||
parameter.node(module).name.range()
|
||||
}
|
||||
DefinitionKind::VariadicKeywordParameter(parameter) => {
|
||||
parameter.node(module).name.range()
|
||||
}
|
||||
DefinitionKind::Parameter(parameter) => parameter.node(module).parameter.name.range(),
|
||||
DefinitionKind::WithItem(with_item) => with_item.target.node(module).range(),
|
||||
DefinitionKind::MatchPattern(match_pattern) => {
|
||||
match_pattern.identifier.node(module).range()
|
||||
}
|
||||
DefinitionKind::ExceptHandler(handler) => handler.node(module).range(),
|
||||
DefinitionKind::TypeVar(type_var) => type_var.node(module).name.range(),
|
||||
DefinitionKind::ParamSpec(param_spec) => param_spec.node(module).name.range(),
|
||||
DefinitionKind::TypeVarTuple(type_var_tuple) => {
|
||||
type_var_tuple.node(module).name.range()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the [`TextRange`] of the entire definition.
|
||||
pub(crate) fn full_range(&self) -> TextRange {
|
||||
pub(crate) fn full_range(&self, module: &ParsedModuleRef) -> TextRange {
|
||||
match self {
|
||||
DefinitionKind::Import(import) => import.alias().range(),
|
||||
DefinitionKind::ImportFrom(import) => import.alias().range(),
|
||||
DefinitionKind::StarImport(import) => import.import().range(),
|
||||
DefinitionKind::Function(function) => function.range(),
|
||||
DefinitionKind::Class(class) => class.range(),
|
||||
DefinitionKind::TypeAlias(type_alias) => type_alias.range(),
|
||||
DefinitionKind::NamedExpression(named) => named.range(),
|
||||
DefinitionKind::Assignment(assignment) => assignment.target.range(),
|
||||
DefinitionKind::AnnotatedAssignment(assign) => assign.target.range(),
|
||||
DefinitionKind::AugmentedAssignment(aug_assign) => aug_assign.range(),
|
||||
DefinitionKind::For(for_stmt) => for_stmt.target.range(),
|
||||
DefinitionKind::Comprehension(comp) => comp.target().range(),
|
||||
DefinitionKind::VariadicPositionalParameter(parameter) => parameter.range(),
|
||||
DefinitionKind::VariadicKeywordParameter(parameter) => parameter.range(),
|
||||
DefinitionKind::Parameter(parameter) => parameter.parameter.range(),
|
||||
DefinitionKind::WithItem(with_item) => with_item.target.range(),
|
||||
DefinitionKind::MatchPattern(match_pattern) => match_pattern.identifier.range(),
|
||||
DefinitionKind::ExceptHandler(handler) => handler.node().range(),
|
||||
DefinitionKind::TypeVar(type_var) => type_var.range(),
|
||||
DefinitionKind::ParamSpec(param_spec) => param_spec.range(),
|
||||
DefinitionKind::TypeVarTuple(type_var_tuple) => type_var_tuple.range(),
|
||||
DefinitionKind::Import(import) => import.alias(module).range(),
|
||||
DefinitionKind::ImportFrom(import) => import.alias(module).range(),
|
||||
DefinitionKind::StarImport(import) => import.import(module).range(),
|
||||
DefinitionKind::Function(function) => function.node(module).range(),
|
||||
DefinitionKind::Class(class) => class.node(module).range(),
|
||||
DefinitionKind::TypeAlias(type_alias) => type_alias.node(module).range(),
|
||||
DefinitionKind::NamedExpression(named) => named.node(module).range(),
|
||||
DefinitionKind::Assignment(assignment) => assignment.target.node(module).range(),
|
||||
DefinitionKind::AnnotatedAssignment(assign) => assign.target.node(module).range(),
|
||||
DefinitionKind::AugmentedAssignment(aug_assign) => aug_assign.node(module).range(),
|
||||
DefinitionKind::For(for_stmt) => for_stmt.target.node(module).range(),
|
||||
DefinitionKind::Comprehension(comp) => comp.target(module).range(),
|
||||
DefinitionKind::VariadicPositionalParameter(parameter) => {
|
||||
parameter.node(module).range()
|
||||
}
|
||||
DefinitionKind::VariadicKeywordParameter(parameter) => parameter.node(module).range(),
|
||||
DefinitionKind::Parameter(parameter) => parameter.node(module).parameter.range(),
|
||||
DefinitionKind::WithItem(with_item) => with_item.target.node(module).range(),
|
||||
DefinitionKind::MatchPattern(match_pattern) => {
|
||||
match_pattern.identifier.node(module).range()
|
||||
}
|
||||
DefinitionKind::ExceptHandler(handler) => handler.node(module).range(),
|
||||
DefinitionKind::TypeVar(type_var) => type_var.node(module).range(),
|
||||
DefinitionKind::ParamSpec(param_spec) => param_spec.node(module).range(),
|
||||
DefinitionKind::TypeVarTuple(type_var_tuple) => type_var_tuple.node(module).range(),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn category(&self, in_stub: bool) -> DefinitionCategory {
|
||||
pub(crate) fn category(&self, in_stub: bool, module: &ParsedModuleRef) -> DefinitionCategory {
|
||||
match self {
|
||||
// functions, classes, and imports always bind, and we consider them declarations
|
||||
DefinitionKind::Function(_)
|
||||
|
|
@ -694,7 +708,7 @@ impl DefinitionKind<'_> {
|
|||
// a parameter always binds a value, but is only a declaration if annotated
|
||||
DefinitionKind::VariadicPositionalParameter(parameter)
|
||||
| DefinitionKind::VariadicKeywordParameter(parameter) => {
|
||||
if parameter.annotation.is_some() {
|
||||
if parameter.node(module).annotation.is_some() {
|
||||
DefinitionCategory::DeclarationAndBinding
|
||||
} else {
|
||||
DefinitionCategory::Binding
|
||||
|
|
@ -702,7 +716,12 @@ impl DefinitionKind<'_> {
|
|||
}
|
||||
// presence of a default is irrelevant, same logic as for a no-default parameter
|
||||
DefinitionKind::Parameter(parameter_with_default) => {
|
||||
if parameter_with_default.parameter.annotation.is_some() {
|
||||
if parameter_with_default
|
||||
.node(module)
|
||||
.parameter
|
||||
.annotation
|
||||
.is_some()
|
||||
{
|
||||
DefinitionCategory::DeclarationAndBinding
|
||||
} else {
|
||||
DefinitionCategory::Binding
|
||||
|
|
@ -753,15 +772,15 @@ pub struct StarImportDefinitionKind {
|
|||
}
|
||||
|
||||
impl StarImportDefinitionKind {
|
||||
pub(crate) fn import(&self) -> &ast::StmtImportFrom {
|
||||
self.node.node()
|
||||
pub(crate) fn import<'ast>(&self, module: &'ast ParsedModuleRef) -> &'ast ast::StmtImportFrom {
|
||||
self.node.node(module)
|
||||
}
|
||||
|
||||
pub(crate) fn alias(&self) -> &ast::Alias {
|
||||
pub(crate) fn alias<'ast>(&self, module: &'ast ParsedModuleRef) -> &'ast ast::Alias {
|
||||
// INVARIANT: for an invalid-syntax statement such as `from foo import *, bar, *`,
|
||||
// we only create a `StarImportDefinitionKind` for the *first* `*` alias in the names list.
|
||||
self.node
|
||||
.node()
|
||||
.node(module)
|
||||
.names
|
||||
.iter()
|
||||
.find(|alias| &alias.name == "*")
|
||||
|
|
@ -784,8 +803,8 @@ pub struct MatchPatternDefinitionKind {
|
|||
}
|
||||
|
||||
impl MatchPatternDefinitionKind {
|
||||
pub(crate) fn pattern(&self) -> &ast::Pattern {
|
||||
self.pattern.node()
|
||||
pub(crate) fn pattern<'ast>(&self, module: &'ast ParsedModuleRef) -> &'ast ast::Pattern {
|
||||
self.pattern.node(module)
|
||||
}
|
||||
|
||||
pub(crate) fn index(&self) -> u32 {
|
||||
|
|
@ -808,16 +827,16 @@ pub struct ComprehensionDefinitionKind<'db> {
|
|||
}
|
||||
|
||||
impl<'db> ComprehensionDefinitionKind<'db> {
|
||||
pub(crate) fn iterable(&self) -> &ast::Expr {
|
||||
self.iterable.node()
|
||||
pub(crate) fn iterable<'ast>(&self, module: &'ast ParsedModuleRef) -> &'ast ast::Expr {
|
||||
self.iterable.node(module)
|
||||
}
|
||||
|
||||
pub(crate) fn target_kind(&self) -> TargetKind<'db> {
|
||||
self.target_kind
|
||||
}
|
||||
|
||||
pub(crate) fn target(&self) -> &ast::Expr {
|
||||
self.target.node()
|
||||
pub(crate) fn target<'ast>(&self, module: &'ast ParsedModuleRef) -> &'ast ast::Expr {
|
||||
self.target.node(module)
|
||||
}
|
||||
|
||||
pub(crate) fn is_first(&self) -> bool {
|
||||
|
|
@ -837,12 +856,12 @@ pub struct ImportDefinitionKind {
|
|||
}
|
||||
|
||||
impl ImportDefinitionKind {
|
||||
pub(crate) fn import(&self) -> &ast::StmtImport {
|
||||
self.node.node()
|
||||
pub(crate) fn import<'ast>(&self, module: &'ast ParsedModuleRef) -> &'ast ast::StmtImport {
|
||||
self.node.node(module)
|
||||
}
|
||||
|
||||
pub(crate) fn alias(&self) -> &ast::Alias {
|
||||
&self.node.node().names[self.alias_index]
|
||||
pub(crate) fn alias<'ast>(&self, module: &'ast ParsedModuleRef) -> &'ast ast::Alias {
|
||||
&self.node.node(module).names[self.alias_index]
|
||||
}
|
||||
|
||||
pub(crate) fn is_reexported(&self) -> bool {
|
||||
|
|
@ -858,12 +877,12 @@ pub struct ImportFromDefinitionKind {
|
|||
}
|
||||
|
||||
impl ImportFromDefinitionKind {
|
||||
pub(crate) fn import(&self) -> &ast::StmtImportFrom {
|
||||
self.node.node()
|
||||
pub(crate) fn import<'ast>(&self, module: &'ast ParsedModuleRef) -> &'ast ast::StmtImportFrom {
|
||||
self.node.node(module)
|
||||
}
|
||||
|
||||
pub(crate) fn alias(&self) -> &ast::Alias {
|
||||
&self.node.node().names[self.alias_index]
|
||||
pub(crate) fn alias<'ast>(&self, module: &'ast ParsedModuleRef) -> &'ast ast::Alias {
|
||||
&self.node.node(module).names[self.alias_index]
|
||||
}
|
||||
|
||||
pub(crate) fn is_reexported(&self) -> bool {
|
||||
|
|
@ -883,12 +902,12 @@ impl<'db> AssignmentDefinitionKind<'db> {
|
|||
self.target_kind
|
||||
}
|
||||
|
||||
pub(crate) fn value(&self) -> &ast::Expr {
|
||||
self.value.node()
|
||||
pub(crate) fn value<'ast>(&self, module: &'ast ParsedModuleRef) -> &'ast ast::Expr {
|
||||
self.value.node(module)
|
||||
}
|
||||
|
||||
pub(crate) fn target(&self) -> &ast::Expr {
|
||||
self.target.node()
|
||||
pub(crate) fn target<'ast>(&self, module: &'ast ParsedModuleRef) -> &'ast ast::Expr {
|
||||
self.target.node(module)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -900,16 +919,16 @@ pub struct AnnotatedAssignmentDefinitionKind {
|
|||
}
|
||||
|
||||
impl AnnotatedAssignmentDefinitionKind {
|
||||
pub(crate) fn value(&self) -> Option<&ast::Expr> {
|
||||
self.value.as_deref()
|
||||
pub(crate) fn value<'ast>(&self, module: &'ast ParsedModuleRef) -> Option<&'ast ast::Expr> {
|
||||
self.value.as_ref().map(|value| value.node(module))
|
||||
}
|
||||
|
||||
pub(crate) fn annotation(&self) -> &ast::Expr {
|
||||
self.annotation.node()
|
||||
pub(crate) fn annotation<'ast>(&self, module: &'ast ParsedModuleRef) -> &'ast ast::Expr {
|
||||
self.annotation.node(module)
|
||||
}
|
||||
|
||||
pub(crate) fn target(&self) -> &ast::Expr {
|
||||
self.target.node()
|
||||
pub(crate) fn target<'ast>(&self, module: &'ast ParsedModuleRef) -> &'ast ast::Expr {
|
||||
self.target.node(module)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -922,16 +941,16 @@ pub struct WithItemDefinitionKind<'db> {
|
|||
}
|
||||
|
||||
impl<'db> WithItemDefinitionKind<'db> {
|
||||
pub(crate) fn context_expr(&self) -> &ast::Expr {
|
||||
self.context_expr.node()
|
||||
pub(crate) fn context_expr<'ast>(&self, module: &'ast ParsedModuleRef) -> &'ast ast::Expr {
|
||||
self.context_expr.node(module)
|
||||
}
|
||||
|
||||
pub(crate) fn target_kind(&self) -> TargetKind<'db> {
|
||||
self.target_kind
|
||||
}
|
||||
|
||||
pub(crate) fn target(&self) -> &ast::Expr {
|
||||
self.target.node()
|
||||
pub(crate) fn target<'ast>(&self, module: &'ast ParsedModuleRef) -> &'ast ast::Expr {
|
||||
self.target.node(module)
|
||||
}
|
||||
|
||||
pub(crate) const fn is_async(&self) -> bool {
|
||||
|
|
@ -948,16 +967,16 @@ pub struct ForStmtDefinitionKind<'db> {
|
|||
}
|
||||
|
||||
impl<'db> ForStmtDefinitionKind<'db> {
|
||||
pub(crate) fn iterable(&self) -> &ast::Expr {
|
||||
self.iterable.node()
|
||||
pub(crate) fn iterable<'ast>(&self, module: &'ast ParsedModuleRef) -> &'ast ast::Expr {
|
||||
self.iterable.node(module)
|
||||
}
|
||||
|
||||
pub(crate) fn target_kind(&self) -> TargetKind<'db> {
|
||||
self.target_kind
|
||||
}
|
||||
|
||||
pub(crate) fn target(&self) -> &ast::Expr {
|
||||
self.target.node()
|
||||
pub(crate) fn target<'ast>(&self, module: &'ast ParsedModuleRef) -> &'ast ast::Expr {
|
||||
self.target.node(module)
|
||||
}
|
||||
|
||||
pub(crate) const fn is_async(&self) -> bool {
|
||||
|
|
@ -972,12 +991,18 @@ pub struct ExceptHandlerDefinitionKind {
|
|||
}
|
||||
|
||||
impl ExceptHandlerDefinitionKind {
|
||||
pub(crate) fn node(&self) -> &ast::ExceptHandlerExceptHandler {
|
||||
self.handler.node()
|
||||
pub(crate) fn node<'ast>(
|
||||
&self,
|
||||
module: &'ast ParsedModuleRef,
|
||||
) -> &'ast ast::ExceptHandlerExceptHandler {
|
||||
self.handler.node(module)
|
||||
}
|
||||
|
||||
pub(crate) fn handled_exceptions(&self) -> Option<&ast::Expr> {
|
||||
self.node().type_.as_deref()
|
||||
pub(crate) fn handled_exceptions<'ast>(
|
||||
&self,
|
||||
module: &'ast ParsedModuleRef,
|
||||
) -> Option<&'ast ast::Expr> {
|
||||
self.node(module).type_.as_deref()
|
||||
}
|
||||
|
||||
pub(crate) fn is_star(&self) -> bool {
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ use crate::ast_node_ref::AstNodeRef;
|
|||
use crate::db::Db;
|
||||
use crate::semantic_index::place::{FileScopeId, ScopeId};
|
||||
use ruff_db::files::File;
|
||||
use ruff_db::parsed::ParsedModuleRef;
|
||||
use ruff_python_ast as ast;
|
||||
use salsa;
|
||||
|
||||
|
|
@ -41,8 +42,8 @@ pub(crate) struct Expression<'db> {
|
|||
/// The expression node.
|
||||
#[no_eq]
|
||||
#[tracked]
|
||||
#[returns(deref)]
|
||||
pub(crate) node_ref: AstNodeRef<ast::Expr>,
|
||||
#[returns(ref)]
|
||||
pub(crate) _node_ref: AstNodeRef<ast::Expr>,
|
||||
|
||||
/// An assignment statement, if this expression is immediately used as the rhs of that
|
||||
/// assignment.
|
||||
|
|
@ -62,6 +63,14 @@ pub(crate) struct Expression<'db> {
|
|||
}
|
||||
|
||||
impl<'db> Expression<'db> {
|
||||
pub(crate) fn node_ref<'ast>(
|
||||
self,
|
||||
db: &'db dyn Db,
|
||||
parsed: &'ast ParsedModuleRef,
|
||||
) -> &'ast ast::Expr {
|
||||
self._node_ref(db).node(parsed)
|
||||
}
|
||||
|
||||
pub(crate) fn scope(self, db: &'db dyn Db) -> ScopeId<'db> {
|
||||
self.file_scope(db).to_scope_id(db, self.file(db))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ use std::ops::Range;
|
|||
use bitflags::bitflags;
|
||||
use hashbrown::hash_map::RawEntryMut;
|
||||
use ruff_db::files::File;
|
||||
use ruff_db::parsed::ParsedModule;
|
||||
use ruff_db::parsed::ParsedModuleRef;
|
||||
use ruff_index::{IndexVec, newtype_index};
|
||||
use ruff_python_ast as ast;
|
||||
use ruff_python_ast::name::Name;
|
||||
|
|
@ -381,16 +381,19 @@ impl<'db> ScopeId<'db> {
|
|||
}
|
||||
|
||||
#[cfg(test)]
|
||||
pub(crate) fn name(self, db: &'db dyn Db) -> &'db str {
|
||||
pub(crate) fn name<'ast>(self, db: &'db dyn Db, module: &'ast ParsedModuleRef) -> &'ast str {
|
||||
match self.node(db) {
|
||||
NodeWithScopeKind::Module => "<module>",
|
||||
NodeWithScopeKind::Class(class) | NodeWithScopeKind::ClassTypeParameters(class) => {
|
||||
class.name.as_str()
|
||||
class.node(module).name.as_str()
|
||||
}
|
||||
NodeWithScopeKind::Function(function)
|
||||
| NodeWithScopeKind::FunctionTypeParameters(function) => function.name.as_str(),
|
||||
| NodeWithScopeKind::FunctionTypeParameters(function) => {
|
||||
function.node(module).name.as_str()
|
||||
}
|
||||
NodeWithScopeKind::TypeAlias(type_alias)
|
||||
| NodeWithScopeKind::TypeAliasTypeParameters(type_alias) => type_alias
|
||||
.node(module)
|
||||
.name
|
||||
.as_name_expr()
|
||||
.map(|name| name.id.as_str())
|
||||
|
|
@ -778,7 +781,7 @@ impl NodeWithScopeRef<'_> {
|
|||
/// # Safety
|
||||
/// The node wrapped by `self` must be a child of `module`.
|
||||
#[expect(unsafe_code)]
|
||||
pub(super) unsafe fn to_kind(self, module: ParsedModule) -> NodeWithScopeKind {
|
||||
pub(super) unsafe fn to_kind(self, module: ParsedModuleRef) -> NodeWithScopeKind {
|
||||
unsafe {
|
||||
match self {
|
||||
NodeWithScopeRef::Module => NodeWithScopeKind::Module,
|
||||
|
|
@ -892,34 +895,46 @@ impl NodeWithScopeKind {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn expect_class(&self) -> &ast::StmtClassDef {
|
||||
pub fn expect_class<'ast>(&self, module: &'ast ParsedModuleRef) -> &'ast ast::StmtClassDef {
|
||||
match self {
|
||||
Self::Class(class) => class.node(),
|
||||
Self::Class(class) => class.node(module),
|
||||
_ => panic!("expected class"),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) const fn as_class(&self) -> Option<&ast::StmtClassDef> {
|
||||
pub(crate) fn as_class<'ast>(
|
||||
&self,
|
||||
module: &'ast ParsedModuleRef,
|
||||
) -> Option<&'ast ast::StmtClassDef> {
|
||||
match self {
|
||||
Self::Class(class) => Some(class.node()),
|
||||
Self::Class(class) => Some(class.node(module)),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn expect_function(&self) -> &ast::StmtFunctionDef {
|
||||
self.as_function().expect("expected function")
|
||||
pub fn expect_function<'ast>(
|
||||
&self,
|
||||
module: &'ast ParsedModuleRef,
|
||||
) -> &'ast ast::StmtFunctionDef {
|
||||
self.as_function(module).expect("expected function")
|
||||
}
|
||||
|
||||
pub fn expect_type_alias(&self) -> &ast::StmtTypeAlias {
|
||||
pub fn expect_type_alias<'ast>(
|
||||
&self,
|
||||
module: &'ast ParsedModuleRef,
|
||||
) -> &'ast ast::StmtTypeAlias {
|
||||
match self {
|
||||
Self::TypeAlias(type_alias) => type_alias.node(),
|
||||
Self::TypeAlias(type_alias) => type_alias.node(module),
|
||||
_ => panic!("expected type alias"),
|
||||
}
|
||||
}
|
||||
|
||||
pub const fn as_function(&self) -> Option<&ast::StmtFunctionDef> {
|
||||
pub fn as_function<'ast>(
|
||||
&self,
|
||||
module: &'ast ParsedModuleRef,
|
||||
) -> Option<&'ast ast::StmtFunctionDef> {
|
||||
match self {
|
||||
Self::Function(function) => Some(function.node()),
|
||||
Self::Function(function) => Some(function.node(module)),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ fn exports_cycle_initial(_db: &dyn Db, _file: File) -> Box<[Name]> {
|
|||
|
||||
#[salsa::tracked(returns(deref), cycle_fn=exports_cycle_recover, cycle_initial=exports_cycle_initial)]
|
||||
pub(super) fn exported_names(db: &dyn Db, file: File) -> Box<[Name]> {
|
||||
let module = parsed_module(db.upcast(), file);
|
||||
let module = parsed_module(db.upcast(), file).load(db.upcast());
|
||||
let mut finder = ExportFinder::new(db, file);
|
||||
finder.visit_body(module.suite());
|
||||
finder.resolve_exports()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue