emmylua_code_analysis/db_index/operators/
mod.rs

1mod lua_operator;
2mod lua_operator_meta_method;
3
4use std::collections::HashMap;
5
6use crate::FileId;
7
8use super::traits::LuaIndex;
9pub use lua_operator::{LuaOperator, LuaOperatorId, LuaOperatorOwner, OperatorFunction};
10pub use lua_operator_meta_method::LuaOperatorMetaMethod;
11
12#[derive(Debug)]
13pub struct LuaOperatorIndex {
14    operators: HashMap<LuaOperatorId, LuaOperator>,
15    type_operators_map:
16        HashMap<LuaOperatorOwner, HashMap<LuaOperatorMetaMethod, Vec<LuaOperatorId>>>,
17    in_filed_operator_map: HashMap<FileId, Vec<LuaOperatorId>>,
18}
19
20impl LuaOperatorIndex {
21    pub fn new() -> Self {
22        Self {
23            operators: HashMap::new(),
24            type_operators_map: HashMap::new(),
25            in_filed_operator_map: HashMap::new(),
26        }
27    }
28
29    pub fn add_operator(&mut self, operator: LuaOperator) {
30        let id = operator.get_id();
31        let owner = operator.get_owner().clone();
32        let op = operator.get_op();
33        self.operators.insert(id, operator);
34        self.type_operators_map
35            .entry(owner)
36            .or_insert_with(HashMap::new)
37            .entry(op)
38            .or_insert_with(Vec::new)
39            .push(id);
40        self.in_filed_operator_map
41            .entry(id.file_id)
42            .or_insert_with(Vec::new)
43            .push(id);
44    }
45
46    pub fn get_operators(
47        &self,
48        owner: &LuaOperatorOwner,
49        meta_method: LuaOperatorMetaMethod,
50    ) -> Option<&Vec<LuaOperatorId>> {
51        self.type_operators_map
52            .get(owner)
53            .and_then(|map| map.get(&meta_method))
54    }
55
56    pub fn get_operator(&self, id: &LuaOperatorId) -> Option<&LuaOperator> {
57        self.operators.get(id)
58    }
59}
60
61impl LuaIndex for LuaOperatorIndex {
62    fn remove(&mut self, file_id: FileId) {
63        if let Some(operator_ids) = self.in_filed_operator_map.remove(&file_id) {
64            for id in operator_ids {
65                if let Some(operator) = self.operators.remove(&id) {
66                    let owner = operator.get_owner();
67                    let op = operator.get_op();
68                    let operators_map = match self.type_operators_map.get_mut(owner) {
69                        Some(map) => map,
70                        None => continue,
71                    };
72                    let operators = match operators_map.get_mut(&op) {
73                        Some(operators) => operators,
74                        None => continue,
75                    };
76                    operators.retain(|x| x != &id);
77                    if operators.is_empty() {
78                        operators_map.remove(&op);
79                    }
80
81                    if operators_map.is_empty() {
82                        self.type_operators_map.remove(owner);
83                    }
84                }
85            }
86        }
87    }
88
89    fn clear(&mut self) {
90        self.operators.clear();
91        self.type_operators_map.clear();
92        self.in_filed_operator_map.clear();
93    }
94}