emmylua_code_analysis/db_index/member/
mod.rs

1mod lua_member;
2mod lua_member_feature;
3mod lua_member_item;
4mod lua_member_owner;
5mod lua_owner_members;
6
7use std::collections::{HashMap, HashSet};
8
9use super::traits::LuaIndex;
10use crate::{FileId, db_index::member::lua_owner_members::LuaOwnerMembers};
11pub use lua_member::{LuaMember, LuaMemberId, LuaMemberKey};
12pub use lua_member_feature::LuaMemberFeature;
13pub use lua_member_item::LuaMemberIndexItem;
14pub use lua_member_owner::LuaMemberOwner;
15
16#[derive(Debug)]
17pub struct LuaMemberIndex {
18    members: HashMap<LuaMemberId, LuaMember>,
19    in_filed: HashMap<FileId, HashSet<MemberOrOwner>>,
20    owner_members: HashMap<LuaMemberOwner, LuaOwnerMembers>,
21    member_current_owner: HashMap<LuaMemberId, LuaMemberOwner>,
22}
23
24#[derive(Debug, Clone, PartialEq, Eq, Hash)]
25enum MemberOrOwner {
26    Member(LuaMemberId),
27    Owner(LuaMemberOwner),
28}
29
30impl Default for LuaMemberIndex {
31    fn default() -> Self {
32        Self::new()
33    }
34}
35
36impl LuaMemberIndex {
37    pub fn new() -> Self {
38        Self {
39            members: HashMap::new(),
40            in_filed: HashMap::new(),
41            owner_members: HashMap::new(),
42            member_current_owner: HashMap::new(),
43        }
44    }
45
46    pub fn add_member(&mut self, owner: LuaMemberOwner, member: LuaMember) -> LuaMemberId {
47        let id = member.get_id();
48        let file_id = member.get_file_id();
49        self.members.insert(id, member);
50        self.add_in_file_object(file_id, MemberOrOwner::Member(id));
51        if !owner.is_unknown() {
52            self.member_current_owner.insert(id, owner.clone());
53            self.add_in_file_object(file_id, MemberOrOwner::Owner(owner.clone()));
54            self.add_member_to_owner(owner.clone(), id);
55        }
56        id
57    }
58
59    fn add_in_file_object(&mut self, file_id: FileId, member_or_owner: MemberOrOwner) {
60        self.in_filed
61            .entry(file_id)
62            .or_default()
63            .insert(member_or_owner);
64    }
65
66    pub fn add_member_to_owner(&mut self, owner: LuaMemberOwner, id: LuaMemberId) -> Option<()> {
67        let member = self.get_member(&id)?;
68        let key = member.get_key().clone();
69        let feature = member.get_feature();
70        let member_map = self
71            .owner_members
72            .entry(owner.clone())
73            .or_insert_with(LuaOwnerMembers::new);
74        if feature.is_decl() {
75            if let Some(item) = member_map.get_member_mut(&key) {
76                match item {
77                    LuaMemberIndexItem::One(old_id) => {
78                        if old_id != &id {
79                            let ids = vec![*old_id, id];
80                            *item = LuaMemberIndexItem::Many(ids);
81                        }
82                    }
83                    LuaMemberIndexItem::Many(ids) => {
84                        if !ids.contains(&id) {
85                            ids.push(id);
86                        }
87                    }
88                }
89            } else {
90                member_map.add_member(key.clone(), LuaMemberIndexItem::One(id));
91            }
92        } else {
93            if !member_map.contains_member(&key) {
94                member_map.add_member(key, LuaMemberIndexItem::One(id));
95                return Some(());
96            }
97
98            let item = member_map.get_member(&key)?.clone();
99            let new_items = if self.is_item_only_meta(&item) {
100                match item {
101                    LuaMemberIndexItem::One(old_id) => {
102                        if old_id == id {
103                            return Some(());
104                        }
105                        LuaMemberIndexItem::Many(vec![id, old_id])
106                    }
107                    LuaMemberIndexItem::Many(mut ids) => {
108                        if ids.contains(&id) {
109                            return Some(());
110                        }
111
112                        ids.push(id);
113                        LuaMemberIndexItem::Many(ids)
114                    }
115                }
116            } else {
117                return Some(());
118            };
119
120            self.owner_members
121                .entry(owner.clone())
122                .or_insert_with(LuaOwnerMembers::new)
123                .add_member(key.clone(), new_items);
124        }
125
126        Some(())
127    }
128
129    fn is_item_only_meta(&self, item: &LuaMemberIndexItem) -> bool {
130        match item {
131            LuaMemberIndexItem::One(id) => {
132                if let Some(member) = self.get_member(id) {
133                    return member.get_feature().is_meta_decl();
134                }
135            }
136            LuaMemberIndexItem::Many(ids) => {
137                for id in ids {
138                    if let Some(member) = self.get_member(id)
139                        && !member.get_feature().is_meta_decl()
140                    {
141                        return false;
142                    }
143                }
144                return true;
145            }
146        }
147
148        false
149    }
150
151    pub fn set_member_owner(
152        &mut self,
153        owner: LuaMemberOwner,
154        file_id: FileId,
155        id: LuaMemberId,
156    ) -> Option<()> {
157        self.member_current_owner.insert(id, owner.clone());
158        self.add_in_file_object(file_id, MemberOrOwner::Owner(owner));
159
160        Some(())
161    }
162
163    pub fn get_member(&self, id: &LuaMemberId) -> Option<&LuaMember> {
164        self.members.get(id)
165    }
166
167    pub fn get_member_mut(&mut self, id: &LuaMemberId) -> Option<&mut LuaMember> {
168        self.members.get_mut(id)
169    }
170
171    pub fn get_members(&self, owner: &LuaMemberOwner) -> Option<Vec<&LuaMember>> {
172        let member_items = self.owner_members.get(owner)?;
173        let mut members = Vec::new();
174        for item in member_items.get_member_items() {
175            match item {
176                LuaMemberIndexItem::One(id) => {
177                    if let Some(member) = self.get_member(id) {
178                        members.push(member);
179                    }
180                }
181                LuaMemberIndexItem::Many(ids) => {
182                    for id in ids {
183                        if let Some(member) = self.get_member(id) {
184                            members.push(member);
185                        }
186                    }
187                }
188            }
189        }
190
191        Some(members)
192    }
193
194    #[allow(unused)]
195    pub fn get_member_item_by_member_id(
196        &self,
197        member_id: LuaMemberId,
198    ) -> Option<&LuaMemberIndexItem> {
199        let owner = self.member_current_owner.get(&member_id)?;
200        let member_key = self.members.get(&member_id)?.get_key();
201        let member_items = self.owner_members.get(owner)?;
202        let item = member_items.get_member(member_key)?;
203        Some(item)
204    }
205
206    pub fn get_sorted_members(&self, owner: &LuaMemberOwner) -> Option<Vec<&LuaMember>> {
207        let mut members = self.get_members(owner)?;
208        members.sort_by_key(|member| member.get_sort_key());
209        Some(members)
210    }
211
212    pub fn get_member_item(
213        &self,
214        owner: &LuaMemberOwner,
215        key: &LuaMemberKey,
216    ) -> Option<&LuaMemberIndexItem> {
217        self.owner_members
218            .get(owner)
219            .and_then(|map| map.get_member(key))
220    }
221
222    pub fn get_member_len(&self, owner: &LuaMemberOwner) -> usize {
223        self.owner_members
224            .get(owner)
225            .map_or(0, |map| map.get_member_len())
226    }
227
228    pub fn get_current_owner(&self, id: &LuaMemberId) -> Option<&LuaMemberOwner> {
229        self.member_current_owner.get(id)
230    }
231}
232
233impl LuaIndex for LuaMemberIndex {
234    fn remove(&mut self, file_id: FileId) {
235        if let Some(member_ids) = self.in_filed.remove(&file_id) {
236            let mut owners = HashSet::new();
237            for member_id_or_owner in member_ids {
238                match member_id_or_owner {
239                    MemberOrOwner::Member(member_id) => {
240                        self.members.remove(&member_id);
241                        self.member_current_owner.remove(&member_id);
242                    }
243                    MemberOrOwner::Owner(owner) => {
244                        owners.insert(owner);
245                    }
246                }
247            }
248
249            let mut need_removed_owner = Vec::new();
250            for owner in owners {
251                if let Some(member_items) = self.owner_members.get_mut(&owner) {
252                    let mut need_removed_key = Vec::new();
253                    for (key, item) in member_items.iter_mut() {
254                        match item {
255                            LuaMemberIndexItem::One(id) => {
256                                if id.file_id == file_id {
257                                    need_removed_key.push(key.clone());
258                                }
259                            }
260                            LuaMemberIndexItem::Many(ids) => {
261                                ids.retain(|id| id.file_id != file_id);
262                                if ids.is_empty() {
263                                    need_removed_key.push(key.clone());
264                                }
265                            }
266                        }
267                    }
268
269                    for key in need_removed_key {
270                        member_items.remove_member(&key);
271                    }
272
273                    if member_items.is_empty() {
274                        need_removed_owner.push(owner);
275                    }
276                }
277            }
278
279            for owner in need_removed_owner {
280                self.owner_members.remove(&owner);
281            }
282        }
283    }
284
285    fn clear(&mut self) {
286        self.members.clear();
287        self.in_filed.clear();
288        self.owner_members.clear();
289    }
290}