1use oxc_syntax::node::NodeId;
2
3#[derive(Debug)]
4pub struct LabeledScope<'a> {
5 pub name: &'a str,
6 pub used: bool,
7 pub node_id: NodeId,
8}
9
10#[derive(Debug, Default)]
11pub struct UnusedLabels<'a> {
12 pub stack: Vec<LabeledScope<'a>>,
13 pub labels: Vec<NodeId>,
14}
15
16impl<'a> UnusedLabels<'a> {
17 pub fn add(&mut self, name: &'a str, node_id: NodeId) {
18 self.stack.push(LabeledScope { name, used: false, node_id });
19 }
20
21 pub fn reference(&mut self, name: &'a str) {
22 for scope in self.stack.iter_mut().rev() {
23 if scope.name == name {
24 scope.used = true;
25 return;
26 }
27 }
28 }
29
30 pub fn mark_unused(&mut self) {
31 debug_assert!(
32 !self.stack.is_empty(),
33 "mark_unused called with empty label stack - this indicates mismatched add/mark_unused calls"
34 );
35
36 if let Some(scope) = self.stack.pop()
37 && !scope.used
38 {
39 self.labels.push(scope.node_id);
40 }
41 }
42
43 #[cfg(debug_assertions)]
44 pub fn assert_empty(&self) {
45 debug_assert!(
46 self.stack.is_empty(),
47 "Label stack not empty at end of processing - {} labels remaining. This indicates mismatched add/mark_unused calls",
48 self.stack.len()
49 );
50 }
51}