clangd_parser/
symbols.rs

1use crate::clangd::ClangdUtility;
2use griff::ChunkStream;
3
4#[derive(Debug, Clone, Default, PartialEq)]
5#[repr(u8)]
6pub enum SymbolKind {
7    #[default]
8    Unknown = 0,
9
10    Module,
11    Namespace,
12    NamespaceAlias,
13    Macro,
14   
15    Enum,
16    Struct,
17    Class,
18    Protocol,
19    Extension,
20    Union,
21    TypeAlias,
22   
23    Function,
24    Variable,
25    Field,
26    EnumConstant,
27   
28    InstanceMethod,
29    ClassMethod,
30    StaticMethod,
31    InstanceProperty,
32    ClassProperty,
33    StaticProperty,
34   
35    Constructor,
36    Destructor,
37    ConversionFunction,
38   
39    Parameter,
40    Using,
41    TemplateTypeParm,
42    TemplateTemplateParm,
43    NonTypeTemplateParm,
44}
45impl From<u8> for SymbolKind {
46    fn from(b: u8) -> Self {
47        use SymbolKind::*;
48        match b {
49            1 => Module,
50            2 => Namespace,
51            3 => NamespaceAlias,
52            4 => Macro,
53            5 => Enum,
54            6 => Struct,
55            7 => Class,
56            8 => Protocol,
57            9 => Extension,
58            10 => Union,
59            11 => TypeAlias,
60            12 => Function,
61            13 => Variable,
62            14 => Field,
63            15 => EnumConstant,
64            16 => InstanceMethod,
65            17 => ClassMethod,
66            18 => StaticMethod,
67            19 => InstanceProperty,
68            20 => ClassProperty,
69            21 => StaticProperty,
70            22 => Constructor,
71            23 => Destructor,
72            24 => ConversionFunction,
73            25 => Parameter,
74            26 => Using,
75            27 => TemplateTypeParm,
76            28 => TemplateTemplateParm,
77            29 => NonTypeTemplateParm,
78
79            _ => Unknown,
80        }
81    }
82}
83
84#[derive(Debug, Clone, Default)]
85#[repr(u8)]
86pub enum SymbolLanguage {
87    #[default]
88    C,
89
90    ObjC,
91    CXX,
92    Swift,
93}
94impl From<u8> for SymbolLanguage {
95    fn from(b: u8) -> Self {
96        use SymbolLanguage::*;
97
98        match b {
99            1 => ObjC,
100            2 => CXX,
101            3 => Swift,
102            _ => C,
103        }
104    }
105}
106
107#[derive(Debug, Clone, Default)]
108#[repr(u8)]
109#[allow(dead_code)]
110pub enum SymbolSubKind {
111    #[default]
112    None,
113    CXXCopyConstructor,
114    CXXMoveConstructor,
115    AccessorGetter,
116    AccessorSetter,
117    UsingTypename,
118    UsingValue,
119    UsingEnum,
120}
121
122#[derive(Debug, Clone, Default)]
123#[repr(u16)]
124#[allow(dead_code)]
125pub enum SymbolProperty {
126    #[default]
127    Unknown,
128
129    Generic                       = 1 << 0,
130    TemplatePartialSpecialization = 1 << 1,
131    TemplateSpecialization        = 1 << 2,
132    UnitTest                      = 1 << 3,
133    IBAnnotated                   = 1 << 4,
134    IBOutletCollection            = 1 << 5,
135    GKInspectable                 = 1 << 6,
136    Local                         = 1 << 7,
137}
138pub type SymbolPropertySet = u16;
139
140#[derive(Debug, Clone, Default)]
141pub struct SymbolInfo {
142    pub kind: SymbolKind,
143    pub subkind: SymbolSubKind,
144    pub lang: SymbolLanguage,
145    pub properties: SymbolPropertySet,
146}
147
148#[derive(Debug, Clone, Default)]
149pub struct SymbolLocation {
150    pub start: SymbolPosition,
151    pub end: SymbolPosition,
152    pub file_uri: String,
153}
154impl SymbolLocation {
155    pub fn get_location(buf: &[u8], string_table: &Vec<String>) -> (usize, Self) {
156        let mut loc: SymbolLocation = Default::default();
157        let mut bytes_read: usize = 0;
158        let (sz, content) = Symbol::get_string(buf, string_table);
159        loc.file_uri = content;
160        bytes_read += sz;
161
162        let (sz, content) = Symbol::get_varint(buf.get(bytes_read..).unwrap());
163        loc.start.line = content;
164        bytes_read += sz;
165        let (sz, content) = Symbol::get_varint(buf.get(bytes_read..).unwrap());
166        loc.start.column = content;
167        bytes_read += sz;
168
169        let (sz, content) = Symbol::get_varint(buf.get(bytes_read..).unwrap());
170        loc.end.line = content;
171        bytes_read += sz;
172        let (sz, content) = Symbol::get_varint(buf.get(bytes_read..).unwrap());
173        loc.end.column = content;
174        bytes_read += sz;
175
176        (bytes_read, loc)
177    }
178}
179
180#[derive(Debug, Clone, Default)]
181pub struct SymbolPosition {
182    pub line: u32,
183    pub column: u32,
184}
185
186#[derive(Debug, Clone, Default)]
187#[repr(u16)]
188#[allow(dead_code)]
189pub enum SymbolOrigin {
190    #[default]
191    Unknown = 0,
192
193    AST = 1 << 0,
194    Open = 1 << 1,
195    Static = 1 << 2,
196    Merge = 1 << 3,
197    Identifier = 1 << 4,
198    Remote = 1 << 5,
199    Preamble = 1 << 6,
200    Background = 1 << 8,
201    StdLib = 1 << 9,
202}
203
204#[derive(Debug, Clone, Default)]
205#[repr(u8)]
206pub enum SymbolFlags {
207    #[default]
208    None,
209
210    IndexedForCodeCompletion = 1 << 0,
211    Deprecated = 1 << 1,
212    ImplementationDetail = 1 << 2,
213    VisibleOutsideFile = 1 << 3,
214}
215impl From<u8> for SymbolFlags {
216    fn from(b: u8) -> Self {
217        use SymbolFlags::*;
218
219        match b {
220            1 => IndexedForCodeCompletion,
221            2 => Deprecated,
222            4 => ImplementationDetail,
223            8 => VisibleOutsideFile,
224
225            _ => None,
226        }
227    }
228}
229
230#[derive(Debug, Clone, Default)]
231pub struct SymbolIncludedHeader {
232    pub name: String,
233    pub refs: usize,
234    pub supported_directives: usize,
235}
236
237pub type SymbolId = [u8; 8];
238
239#[derive(Debug, Clone, Default)]
240pub struct Symbol {
241    pub id: SymbolId,
242    pub syminfo: SymbolInfo,
243    pub name: String,
244    pub scope: String,
245    pub definition: SymbolLocation,
246    pub canonical_declaration: SymbolLocation,
247    pub references: u32,
248    pub flags: SymbolFlags,
249    pub origin: SymbolOrigin,
250    pub signature: String,
251    pub template_specialization_args: String,
252    pub completion_snippet_suffix: String,
253    pub documentation: String,
254    pub return_t: String,
255    pub t: String,
256    pub headers: Vec<SymbolIncludedHeader>,
257}
258impl ClangdUtility for Symbol {}
259
260impl Symbol {
261    pub fn parse(stream: &ChunkStream, string_table: &Vec<String>) -> Vec<Symbol> {
262        let mut syms: Vec<Symbol> = vec![];
263        let len = stream.data.len();
264        let data = stream.data.as_slice();
265        if data.len() == 0 {
266            return syms;
267        }
268        let mut cursor: usize = 0;
269        let mut idx: u32;
270        loop {
271            let mut s: Symbol = Default::default();
272            s.id = data.get(cursor..cursor+8).unwrap().try_into().unwrap();
273            cursor += 8;
274            // KIND
275            s.syminfo.kind = SymbolKind::from(data[cursor]);
276            cursor += 1;
277            // LANGUAGE
278            s.syminfo.lang = SymbolLanguage::from(data[cursor]);
279            cursor += 1;
280            let (sz, content) = Self::get_string(&data.get(cursor..).unwrap(), string_table);
281            s.name = content;
282            cursor += sz;
283            // SCOPE
284            let (sz, content) = Self::get_string(&data.get(cursor..).unwrap(), string_table);
285            s.scope = content;
286            cursor += sz;
287            // TEMPLATE SPECIALIZATION ARGUMENTS
288            let (sz, content) = Self::get_string(&data.get(cursor..).unwrap(), string_table);
289            s.template_specialization_args = content;
290            cursor += sz;
291            // LOCATION
292            let (sz, loc) = SymbolLocation::get_location(&data.get(cursor..).unwrap(), string_table);
293            s.definition = loc;
294            cursor += sz;
295            // CANONICAL DECLARATION
296            let (sz, loc) = SymbolLocation::get_location(&data.get(cursor..).unwrap(), string_table);
297            s.canonical_declaration = loc;
298            cursor += sz;
299            // REFERENCES
300            let (sz, content) = Self::get_varint(&data.get(cursor..).unwrap());
301            s.references = content;
302            cursor += sz;
303            // FLAGS
304            s.flags = SymbolFlags::from(*data.get(cursor).unwrap());
305            cursor += 1;
306            // SIGNATURE
307            let (sz, content) = Self::get_string(&data.get(cursor..).unwrap(), string_table);
308            s.signature = content;
309            cursor += sz;
310            // COMPLETION SNIPPET SUFFIX
311            let (sz, content) = Self::get_string(&data.get(cursor..).unwrap(), string_table);
312            s.completion_snippet_suffix = content;
313            cursor += sz;
314            // DOCUMENTATION
315            let (sz, content) = Self::get_string(&data.get(cursor..).unwrap(), string_table);
316            s.documentation = content;
317            cursor += sz;
318            // RETURN TYPE
319            let (sz, content) = Self::get_string(&data.get(cursor..).unwrap(), string_table);
320            s.return_t = content;
321            cursor += sz;
322            // TYPE
323            let (sz, content) = Self::get_string(&data.get(cursor..).unwrap(), string_table);
324            s.t = content;
325            cursor += sz;
326            // INCLUDES
327            let (sz, h_content) = Self::get_varint(&data.get(cursor..).unwrap());
328            cursor += sz;
329            idx = 0;
330            while idx < h_content {
331                let mut hdr: SymbolIncludedHeader = Default::default();
332                let (sz, content) = Self::get_string(&data.get(cursor..).unwrap(), string_table);
333                hdr.name = content;
334                cursor += sz;
335                let (sz, content) = Self::get_varint(&data.get(cursor..).unwrap());
336                hdr.refs = (content >> 2) as usize;
337                hdr.supported_directives = (content & 0x3) as usize;
338                s.headers.push(hdr);
339                cursor += sz;
340                idx += 1;
341            }
342            syms.push(s.clone());
343            if cursor >= len {
344                break;
345            }
346        }
347        syms
348    }
349}