Skip to main content

ty_python_core/
statement.rs

1use crate::ast_node_ref::AstNodeRef;
2use crate::db::Db;
3use crate::definition::Definition;
4use crate::expression::Expression;
5use crate::node_key::NodeKey;
6use crate::scope::{FileScopeId, ScopeId};
7use crate::{Program, ProgramFile};
8use ruff_db::PythonFile;
9use ruff_db::files::File;
10use ruff_python_ast as ast;
11use salsa;
12
13/// An independently type-inferable statement.
14///
15/// Many statements can be treated directly as definitions or expressions,
16/// and so do not require a separate Salsa allocation.
17#[derive(
18    Clone, Copy, Debug, Eq, Hash, PartialEq, salsa::Supertype, get_size2::GetSize, salsa::SalsaValue,
19)]
20pub enum Statement<'db> {
21    Expression(Expression<'db>),
22    Definition(Definition<'db>),
23    Other(StatementInner<'db>),
24}
25
26/// An independently type-inferable statement.
27///
28/// ## Module-local type
29/// This type should not be used as part of any cross-module API because
30/// it holds a reference to the AST node. Range-offset changes
31/// then propagate through all usages, and deserialization requires
32/// reparsing the entire module.
33///
34/// E.g. don't use this type in:
35///
36/// * a return type of a cross-module query
37/// * a field of a type that is a return type of a cross-module query
38/// * an argument of a cross-module query
39#[salsa::tracked(debug, heap_size=ruff_memory_usage::heap_size)]
40pub struct StatementInner<'db> {
41    /// The file in which the statement occurs.
42    #[returns(copy)]
43    pub program_file: ProgramFile<'db>,
44
45    /// The scope in which the statement occurs.
46    #[returns(copy)]
47    pub file_scope: FileScopeId,
48
49    /// The statement node.
50    #[no_eq]
51    #[tracked]
52    #[returns(ref)]
53    pub node_ref: AstNodeRef<ast::Stmt>,
54}
55
56// The Salsa heap is tracked separately.
57impl get_size2::GetSize for StatementInner<'_> {}
58
59impl<'db> StatementInner<'db> {
60    pub fn file(self, db: &'db dyn Db) -> File {
61        self.program_file(db).file(db)
62    }
63
64    pub fn python_file(self, db: &'db dyn Db) -> PythonFile<'db> {
65        self.program_file(db).python_file(db)
66    }
67
68    pub fn scope(self, db: &'db dyn Db) -> ScopeId<'db> {
69        self.file_scope(db).to_scope_id(db, self.program_file(db))
70    }
71
72    pub fn program(self, db: &'db dyn Db) -> Program<'db> {
73        self.scope(db).program(db)
74    }
75}
76
77#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug, get_size2::GetSize, salsa::SalsaValue)]
78pub struct StatementNodeKey(NodeKey);
79
80impl From<&ast::Stmt> for StatementNodeKey {
81    fn from(node: &ast::Stmt) -> Self {
82        Self(NodeKey::from_node(node))
83    }
84}