emmylua_code_analysis/db_index/member/
mod.rs1mod 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}