emmylua_code_analysis/db_index/member/
lua_member.rs

1use emmylua_parser::{LuaDocFieldKey, LuaIndexKey, LuaSyntaxId, LuaSyntaxKind};
2use rowan::{TextRange, TextSize};
3use serde::{Deserialize, Serialize};
4use smol_str::SmolStr;
5
6use super::lua_member_feature::LuaMemberFeature;
7use crate::{FileId, GlobalId};
8
9#[derive(Debug)]
10pub struct LuaMember {
11    member_id: LuaMemberId,
12    key: LuaMemberKey,
13    feature: LuaMemberFeature,
14    global_id: Option<GlobalId>,
15}
16
17impl LuaMember {
18    pub fn new(
19        member_id: LuaMemberId,
20        key: LuaMemberKey,
21        decl_feature: LuaMemberFeature,
22        global_path: Option<GlobalId>,
23    ) -> Self {
24        Self {
25            member_id,
26            key,
27            feature: decl_feature,
28            global_id: global_path,
29        }
30    }
31
32    pub fn get_key(&self) -> &LuaMemberKey {
33        &self.key
34    }
35
36    pub fn get_file_id(&self) -> FileId {
37        self.member_id.file_id
38    }
39
40    pub fn get_range(&self) -> TextRange {
41        self.member_id.get_syntax_id().get_range()
42    }
43
44    pub fn get_sort_key(&self) -> u64 {
45        let file_id = self.member_id.file_id.id;
46        let pos = u32::from(self.member_id.id.get_range().start());
47        (file_id as u64) << 32 | pos as u64
48    }
49
50    pub fn get_syntax_id(&self) -> LuaSyntaxId {
51        *self.member_id.get_syntax_id()
52    }
53
54    pub fn get_id(&self) -> LuaMemberId {
55        self.member_id
56    }
57
58    pub fn is_field(&self) -> bool {
59        LuaSyntaxKind::DocTagField == self.member_id.get_syntax_id().get_kind().into()
60    }
61
62    pub fn get_feature(&self) -> LuaMemberFeature {
63        self.feature
64    }
65
66    pub fn get_global_id(&self) -> Option<&GlobalId> {
67        self.global_id.as_ref()
68    }
69}
70
71#[derive(Debug, Eq, PartialEq, Clone, Copy, Hash, Serialize, Deserialize)]
72pub struct LuaMemberId {
73    pub file_id: FileId,
74    id: LuaSyntaxId,
75}
76
77impl LuaMemberId {
78    pub fn new(id: LuaSyntaxId, file_id: FileId) -> Self {
79        Self { id, file_id }
80    }
81
82    pub fn get_syntax_id(&self) -> &LuaSyntaxId {
83        &self.id
84    }
85
86    pub fn get_position(&self) -> TextSize {
87        self.id.get_range().start()
88    }
89}
90
91#[derive(Debug, Clone, PartialEq, Eq, Hash)]
92pub enum LuaMemberKey {
93    None,
94    Integer(i64),
95    Name(SmolStr),
96    SyntaxId(LuaSyntaxId),
97}
98
99impl LuaMemberKey {
100    pub fn is_none(&self) -> bool {
101        matches!(self, LuaMemberKey::None)
102    }
103
104    pub fn is_name(&self) -> bool {
105        matches!(self, LuaMemberKey::Name(_))
106    }
107
108    pub fn is_integer(&self) -> bool {
109        matches!(self, LuaMemberKey::Integer(_))
110    }
111
112    pub fn is_syntax_id(&self) -> bool {
113        matches!(self, LuaMemberKey::SyntaxId(_))
114    }
115
116    pub fn get_name(&self) -> Option<&str> {
117        match self {
118            LuaMemberKey::Name(name) => Some(name.as_ref()),
119            _ => None,
120        }
121    }
122
123    pub fn get_integer(&self) -> Option<i64> {
124        match self {
125            LuaMemberKey::Integer(i) => Some(*i),
126            _ => None,
127        }
128    }
129
130    pub fn to_path(&self) -> String {
131        match self {
132            LuaMemberKey::Name(name) => name.to_string(),
133            LuaMemberKey::Integer(i) => {
134                format!("[{}]", i)
135            }
136            LuaMemberKey::None => "".to_string(),
137            LuaMemberKey::SyntaxId(_) => "".to_string(),
138        }
139    }
140}
141
142impl PartialOrd for LuaMemberKey {
143    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
144        Some(self.cmp(other))
145    }
146}
147
148impl Ord for LuaMemberKey {
149    fn cmp(&self, other: &Self) -> std::cmp::Ordering {
150        use LuaMemberKey::*;
151        match (self, other) {
152            (None, None) => std::cmp::Ordering::Equal,
153            (None, _) => std::cmp::Ordering::Less,
154            (_, None) => std::cmp::Ordering::Greater,
155            (Integer(a), Integer(b)) => a.cmp(b),
156            (Integer(_), _) => std::cmp::Ordering::Less,
157            (_, Integer(_)) => std::cmp::Ordering::Greater,
158            (Name(a), Name(b)) => a.cmp(b),
159            (Name(_), _) => std::cmp::Ordering::Less,
160            (_, Name(_)) => std::cmp::Ordering::Greater,
161            (SyntaxId(_), SyntaxId(_)) => std::cmp::Ordering::Equal,
162        }
163    }
164}
165
166impl From<LuaIndexKey> for LuaMemberKey {
167    fn from(key: LuaIndexKey) -> Self {
168        match key {
169            LuaIndexKey::Name(name) => LuaMemberKey::Name(name.get_name_text().into()),
170            LuaIndexKey::String(str) => LuaMemberKey::Name(str.get_value().into()),
171            LuaIndexKey::Integer(i) => LuaMemberKey::Integer(i.get_int_value()),
172            LuaIndexKey::Idx(idx) => LuaMemberKey::Integer(idx as i64),
173            _ => LuaMemberKey::None,
174        }
175    }
176}
177
178impl From<&LuaIndexKey> for LuaMemberKey {
179    fn from(key: &LuaIndexKey) -> Self {
180        match key {
181            LuaIndexKey::Name(name) => LuaMemberKey::Name(name.get_name_text().to_string().into()),
182            LuaIndexKey::String(str) => LuaMemberKey::Name(str.get_value().into()),
183            LuaIndexKey::Integer(i) => LuaMemberKey::Integer(i.get_int_value()),
184            _ => LuaMemberKey::None,
185        }
186    }
187}
188
189impl From<LuaDocFieldKey> for LuaMemberKey {
190    fn from(key: LuaDocFieldKey) -> Self {
191        match key {
192            LuaDocFieldKey::Name(name) => {
193                LuaMemberKey::Name(name.get_name_text().to_string().into())
194            }
195            LuaDocFieldKey::String(str) => LuaMemberKey::Name(str.get_value().into()),
196            LuaDocFieldKey::Integer(i) => LuaMemberKey::Integer(i.get_int_value()),
197            _ => LuaMemberKey::None,
198        }
199    }
200}
201
202impl From<&LuaDocFieldKey> for LuaMemberKey {
203    fn from(key: &LuaDocFieldKey) -> Self {
204        match key {
205            LuaDocFieldKey::Name(name) => {
206                LuaMemberKey::Name(name.get_name_text().to_string().into())
207            }
208            LuaDocFieldKey::String(str) => LuaMemberKey::Name(str.get_value().into()),
209            LuaDocFieldKey::Integer(i) => LuaMemberKey::Integer(i.get_int_value()),
210            _ => LuaMemberKey::None,
211        }
212    }
213}
214
215impl From<String> for LuaMemberKey {
216    fn from(name: String) -> Self {
217        LuaMemberKey::Name(name.into())
218    }
219}
220
221impl From<i64> for LuaMemberKey {
222    fn from(i: i64) -> Self {
223        LuaMemberKey::Integer(i)
224    }
225}
226
227impl From<&str> for LuaMemberKey {
228    fn from(name: &str) -> Self {
229        LuaMemberKey::Name(name.to_string().into())
230    }
231}