oxc_semantic/
label.rs

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}