Skip to main content

oxc_semantic/
label.rs

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