emmylua_parser/syntax/node/doc/
mod.rs1mod tag;
2mod types;
3mod description;
4mod test;
5
6pub use description::*;
7pub use tag::*;
8pub use types::*;
9
10use super::{LuaAst, LuaBinaryOpToken, LuaNameToken, LuaNumberToken, LuaStringToken};
11use crate::{
12 kind::{LuaSyntaxKind, LuaTokenKind}, syntax::traits::LuaAstNode, LuaAstChildren, LuaAstToken, LuaAstTokenChildren, LuaKind, LuaSyntaxNode
13};
14
15#[derive(Debug, Clone, PartialEq, Eq, Hash)]
16pub struct LuaComment {
17 syntax: LuaSyntaxNode,
18}
19
20impl LuaAstNode for LuaComment {
21 fn syntax(&self) -> &LuaSyntaxNode {
22 &self.syntax
23 }
24
25 fn can_cast(kind: LuaSyntaxKind) -> bool
26 where
27 Self: Sized,
28 {
29 kind == LuaSyntaxKind::Comment
30 }
31
32 fn cast(syntax: LuaSyntaxNode) -> Option<Self>
33 where
34 Self: Sized,
35 {
36 if Self::can_cast(syntax.kind().into()) {
37 Some(Self { syntax })
38 } else {
39 None
40 }
41 }
42}
43
44impl LuaDocDescriptionOwner for LuaComment {}
45
46impl LuaComment {
47 pub fn get_owner(&self) -> Option<LuaAst> {
48 if let Some(inline_node) = find_inline_node(&self.syntax) {
49 LuaAst::cast(inline_node)
50 } else if let Some(attached_node) = find_attached_node(&self.syntax) {
51 LuaAst::cast(attached_node)
52 } else {
53 None
54 }
55 }
56
57 pub fn get_doc_tags(&self) -> LuaAstChildren<LuaDocTag> {
58 self.children()
59 }
60}
61
62fn find_inline_node(comment: &LuaSyntaxNode) -> Option<LuaSyntaxNode> {
63 let mut prev_sibling = comment.prev_sibling_or_token();
64 loop {
65 if prev_sibling.is_none() {
66 return None;
67 }
68
69 if let Some(sibling) = prev_sibling {
70 match sibling.kind() {
71 LuaKind::Token(
72 LuaTokenKind::TkWhitespace | LuaTokenKind::TkComma | LuaTokenKind::TkSemicolon,
73 ) => {}
74 LuaKind::Token(LuaTokenKind::TkEndOfLine)
75 | LuaKind::Syntax(LuaSyntaxKind::Comment) => {
76 return None;
77 }
78 LuaKind::Token(k) if k != LuaTokenKind::TkName => {
79 return Some(comment.parent()?);
80 }
81 _ => match sibling {
82 rowan::NodeOrToken::Node(node) => {
83 return Some(node);
84 }
85 rowan::NodeOrToken::Token(token) => {
86 return Some(token.parent()?);
87 }
88 },
89 }
90 prev_sibling = sibling.prev_sibling_or_token();
91 } else {
92 return None;
93 }
94 }
95}
96
97fn find_attached_node(comment: &LuaSyntaxNode) -> Option<LuaSyntaxNode> {
98 let mut meet_end_of_line = false;
99
100 let mut next_sibling = comment.next_sibling_or_token();
101 loop {
102 if next_sibling.is_none() {
103 return None;
104 }
105
106 if let Some(sibling) = next_sibling {
107 match sibling.kind() {
108 LuaKind::Token(LuaTokenKind::TkEndOfLine) => {
109 if meet_end_of_line {
110 return None;
111 }
112
113 meet_end_of_line = true;
114 }
115 LuaKind::Token(LuaTokenKind::TkWhitespace) => {}
116 LuaKind::Syntax(LuaSyntaxKind::Comment) => {
117 return None;
118 }
119 LuaKind::Syntax(LuaSyntaxKind::Block) => {
120 let first_child = comment.first_child()?;
121 if first_child.kind() == LuaKind::Syntax(LuaSyntaxKind::Comment) {
122 return None;
123 }
124 return Some(first_child);
125 }
126 _ => match sibling {
127 rowan::NodeOrToken::Node(node) => {
128 return Some(node);
129 }
130 rowan::NodeOrToken::Token(token) => {
131 return Some(token.parent()?);
132 }
133 },
134 }
135 next_sibling = sibling.next_sibling_or_token();
136 }
137 }
138}
139
140#[derive(Debug, Clone, PartialEq, Eq, Hash)]
141pub struct LuaDocGenericDeclList {
142 syntax: LuaSyntaxNode,
143}
144
145impl LuaAstNode for LuaDocGenericDeclList {
146 fn syntax(&self) -> &LuaSyntaxNode {
147 &self.syntax
148 }
149
150 fn can_cast(kind: LuaSyntaxKind) -> bool
151 where
152 Self: Sized,
153 {
154 kind == LuaSyntaxKind::DocGenericDeclareList
155 }
156
157 fn cast(syntax: LuaSyntaxNode) -> Option<Self>
158 where
159 Self: Sized,
160 {
161 if Self::can_cast(syntax.kind().into()) {
162 Some(Self { syntax })
163 } else {
164 None
165 }
166 }
167}
168
169impl LuaDocGenericDeclList {
170 pub fn get_generic_decl(&self) -> LuaAstChildren<LuaDocGenericDecl> {
171 self.children()
172 }
173}
174
175#[derive(Debug, Clone, PartialEq, Eq, Hash)]
176pub struct LuaDocGenericDecl {
177 syntax: LuaSyntaxNode,
178}
179
180impl LuaAstNode for LuaDocGenericDecl {
181 fn syntax(&self) -> &LuaSyntaxNode {
182 &self.syntax
183 }
184
185 fn can_cast(kind: LuaSyntaxKind) -> bool
186 where
187 Self: Sized,
188 {
189 kind == LuaSyntaxKind::DocGenericParameter
190 }
191
192 fn cast(syntax: LuaSyntaxNode) -> Option<Self>
193 where
194 Self: Sized,
195 {
196 if Self::can_cast(syntax.kind().into()) {
197 Some(Self { syntax })
198 } else {
199 None
200 }
201 }
202}
203
204impl LuaDocGenericDecl {
205 pub fn get_name_token(&self) -> Option<LuaNameToken> {
206 self.token()
207 }
208
209 pub fn get_type(&self) -> Option<LuaDocType> {
210 self.child()
211 }
212}
213
214#[derive(Debug, Clone, PartialEq, Eq, Hash)]
215pub struct LuaDocTypeList {
216 syntax: LuaSyntaxNode,
217}
218
219impl LuaAstNode for LuaDocTypeList {
220 fn syntax(&self) -> &LuaSyntaxNode {
221 &self.syntax
222 }
223
224 fn can_cast(kind: LuaSyntaxKind) -> bool
225 where
226 Self: Sized,
227 {
228 kind == LuaSyntaxKind::DocTypeList
229 }
230
231 fn cast(syntax: LuaSyntaxNode) -> Option<Self>
232 where
233 Self: Sized,
234 {
235 if Self::can_cast(syntax.kind().into()) {
236 Some(Self { syntax })
237 } else {
238 None
239 }
240 }
241}
242
243impl LuaDocTypeList {
244 pub fn get_types(&self) -> LuaAstChildren<LuaDocType> {
245 self.children()
246 }
247}
248
249#[derive(Debug, Clone, PartialEq, Eq, Hash)]
250pub struct LuaDocOpType {
251 syntax: LuaSyntaxNode,
252}
253
254impl LuaAstNode for LuaDocOpType {
255 fn syntax(&self) -> &LuaSyntaxNode {
256 &self.syntax
257 }
258
259 fn can_cast(kind: LuaSyntaxKind) -> bool
260 where
261 Self: Sized,
262 {
263 kind == LuaSyntaxKind::DocOpType
264 }
265
266 fn cast(syntax: LuaSyntaxNode) -> Option<Self>
267 where
268 Self: Sized,
269 {
270 if Self::can_cast(syntax.kind().into()) {
271 Some(Self { syntax })
272 } else {
273 None
274 }
275 }
276}
277
278impl LuaDocOpType {
279 pub fn get_op(&self) -> Option<LuaBinaryOpToken> {
280 self.token()
281 }
282
283 pub fn get_type(&self) -> Option<LuaDocType> {
284 self.child()
285 }
286
287 pub fn is_nullable(&self) -> bool {
288 self.token_by_kind(LuaTokenKind::TkDocQuestion).is_some()
289 }
290}
291
292#[derive(Debug, Clone, PartialEq, Eq, Hash)]
293pub struct LuaDocObjectField {
294 syntax: LuaSyntaxNode,
295}
296
297impl LuaAstNode for LuaDocObjectField {
298 fn syntax(&self) -> &LuaSyntaxNode {
299 &self.syntax
300 }
301
302 fn can_cast(kind: LuaSyntaxKind) -> bool
303 where
304 Self: Sized,
305 {
306 kind == LuaSyntaxKind::DocObjectField
307 }
308
309 fn cast(syntax: LuaSyntaxNode) -> Option<Self>
310 where
311 Self: Sized,
312 {
313 if Self::can_cast(syntax.kind().into()) {
314 Some(Self { syntax })
315 } else {
316 None
317 }
318 }
319}
320
321impl LuaDocObjectField {
322 pub fn get_field_key(&self) -> Option<LuaDocObjectFieldKey> {
323 for child in self.syntax.children_with_tokens() {
324 match child.kind() {
325 LuaKind::Token(LuaTokenKind::TkName) => {
326 return LuaNameToken::cast(child.into_token().unwrap()).map(LuaDocObjectFieldKey::Name);
327 }
328 LuaKind::Token(LuaTokenKind::TkString) => {
329 return LuaStringToken::cast(child.into_token().unwrap()).map(LuaDocObjectFieldKey::String);
330 }
331 LuaKind::Token(LuaTokenKind::TkInt) => {
332 return LuaNumberToken::cast(child.into_token().unwrap()).map(LuaDocObjectFieldKey::Integer);
333 }
334 kind if LuaDocType::can_cast(kind.into()) => {
335 return LuaDocType::cast(child.into_node().unwrap()).map(LuaDocObjectFieldKey::Type);
336 }
337 LuaKind::Token(LuaTokenKind::TkColon) => {
338 return None;
339 }
340 _ => {}
341 }
342 }
343
344 None
345 }
346
347 pub fn get_type(&self) -> Option<LuaDocType> {
348 self.children().last()
349 }
350
351 pub fn is_nullable(&self) -> bool {
352 self.token_by_kind(LuaTokenKind::TkDocQuestion).is_some()
353 }
354}
355
356#[derive(Debug, Clone, PartialEq, Eq, Hash)]
357pub enum LuaDocObjectFieldKey {
358 Name(LuaNameToken),
359 String(LuaStringToken),
360 Integer(LuaNumberToken),
361 Type(LuaDocType),
362}
363
364#[derive(Debug, Clone, PartialEq, Eq, Hash)]
365pub struct LuaDocAttribute {
366 syntax: LuaSyntaxNode,
367}
368
369impl LuaAstNode for LuaDocAttribute {
370 fn syntax(&self) -> &LuaSyntaxNode {
371 &self.syntax
372 }
373
374 fn can_cast(kind: LuaSyntaxKind) -> bool
375 where
376 Self: Sized,
377 {
378 kind == LuaSyntaxKind::DocAttribute
379 }
380
381 fn cast(syntax: LuaSyntaxNode) -> Option<Self>
382 where
383 Self: Sized,
384 {
385 if Self::can_cast(syntax.kind().into()) {
386 Some(Self { syntax })
387 } else {
388 None
389 }
390 }
391}
392
393impl LuaDocAttribute {
394 pub fn get_attrib_tokens(&self) -> LuaAstTokenChildren<LuaNameToken> {
395 self.tokens()
396 }
397}