Repository navigation
Expand file tree
/
Copy pathunpack.rs
More file actions
139 lines (119 loc) · 4.44 KB
/
Copy pathunpack.rs
File metadata and controls
139 lines (119 loc) · 4.44 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
use crate::Program;
use ruff_db::PythonFile;
use ruff_db::files::File;
use ruff_db::parsed::ParsedModuleRef;
use ruff_python_ast::{self as ast, AnyNodeRef};
use ruff_text_size::{Ranged, TextRange};
use crate::Db;
use crate::EvaluationMode;
use crate::ProgramFile;
use crate::ast_node_ref::AstNodeRef;
use crate::expression::Expression;
use crate::scope::{FileScopeId, ScopeId};
/// This ingredient represents a single unpacking.
///
/// This is required to make use of salsa to cache the complete unpacking of multiple variables
/// involved. It allows us to:
/// 1. Avoid doing structural match multiple times for each definition
/// 2. Avoid highlighting the same error multiple times
///
/// ## Module-local type
/// This type should not be used as part of any cross-module API because
/// it holds a reference to the AST node. Range-offset changes
/// then propagate through all usages, and deserialization requires
/// reparsing the entire module.
///
/// E.g. don't use this type in:
///
/// * a return type of a cross-module query
/// * a field of a type that is a return type of a cross-module query
/// * an argument of a cross-module query
#[salsa::tracked(debug, heap_size=ruff_memory_usage::heap_size)]
pub struct Unpack<'db> {
#[returns(copy)]
pub program_file: ProgramFile<'db>,
#[returns(copy)]
pub(crate) value_file_scope: FileScopeId,
#[returns(copy)]
pub(crate) target_file_scope: FileScopeId,
/// The target expression that is being unpacked. For example, in `(a, b) = (1, 2)`, the target
/// expression is `(a, b)`.
#[no_eq]
#[tracked]
#[returns(ref)]
pub(crate) _target: AstNodeRef<ast::Expr>,
/// The ingredient representing the value expression of the unpacking. For example, in
/// `(a, b) = (1, 2)`, the value expression is `(1, 2)`.
#[returns(copy)]
pub value: UnpackValue<'db>,
}
// The Salsa heap is tracked separately.
impl get_size2::GetSize for Unpack<'_> {}
impl<'db> Unpack<'db> {
pub fn file(self, db: &'db dyn Db) -> File {
self.program_file(db).file(db)
}
pub fn python_file(self, db: &'db dyn Db) -> PythonFile<'db> {
self.program_file(db).python_file(db)
}
pub fn target<'ast>(self, db: &'db dyn Db, parsed: &'ast ParsedModuleRef) -> &'ast ast::Expr {
self._target(db).node(parsed)
}
/// Returns the scope where the unpack target expression belongs to.
pub fn target_scope(self, db: &'db dyn Db) -> ScopeId<'db> {
self.target_file_scope(db)
.to_scope_id(db, self.program_file(db))
}
pub fn program(self, db: &'db dyn Db) -> Program<'db> {
self.target_scope(db).program(db)
}
/// Returns the range of the unpack target expression.
pub fn range(self, db: &'db dyn Db, module: &ParsedModuleRef) -> TextRange {
self.target(db, module).range()
}
}
/// The expression that is being unpacked.
#[derive(Clone, Copy, Debug, Hash, PartialEq, get_size2::GetSize, salsa::SalsaValue)]
pub struct UnpackValue<'db> {
/// The kind of unpack expression
kind: UnpackKind,
/// The expression we are unpacking
expression: Expression<'db>,
}
impl<'db> UnpackValue<'db> {
pub(crate) fn new(kind: UnpackKind, expression: Expression<'db>) -> Self {
Self { kind, expression }
}
/// Returns the underlying [`Expression`] that is being unpacked.
pub const fn expression(self) -> Expression<'db> {
self.expression
}
/// Returns the expression as an [`AnyNodeRef`].
pub fn as_any_node_ref<'ast>(
self,
db: &'db dyn Db,
module: &'ast ParsedModuleRef,
) -> AnyNodeRef<'ast> {
self.expression().node_ref(db).node(module).into()
}
pub const fn kind(self) -> UnpackKind {
self.kind
}
}
#[derive(Clone, Copy, Debug, Hash, PartialEq, get_size2::GetSize)]
pub enum UnpackKind {
/// An iterable expression like the one in a `for` loop or a comprehension.
Iterable { mode: EvaluationMode },
/// An context manager expression like the one in a `with` statement.
ContextManager { mode: EvaluationMode },
/// An expression that is being assigned to a target.
Assign,
}
/// The position of the target element in an unpacking.
#[derive(Clone, Copy, Debug, Hash, PartialEq, get_size2::GetSize)]
pub enum UnpackPosition {
/// The target element is in the first position of the unpacking.
First,
/// The target element is in the position other than the first position of the unpacking.
Other,
}