glua_parser/syntax/traits/
description_trait.rs1use crate::{LuaAstNode, LuaDocDescription, LuaKind, LuaSyntaxKind, LuaSyntaxNode, LuaTokenKind};
2
3#[allow(unused)]
4pub trait LuaDocDescriptionOwner: LuaAstNode {
5 fn get_description(&self) -> Option<LuaDocDescription> {
6 if let Some(inline_description) = find_inline_description(self.syntax()) {
7 return LuaDocDescription::cast(inline_description);
8 }
9
10 None
11 }
12
13 fn get_descriptions(&self) -> Vec<LuaDocDescription> {
14 let mut descriptions = vec![];
15 if let Some(attached_description) = find_attached_description(self.syntax()) {
16 descriptions.push(LuaDocDescription::cast(attached_description).unwrap());
17 }
18
19 if let Some(inline_description) = find_inline_description(self.syntax()) {
20 descriptions.push(LuaDocDescription::cast(inline_description).unwrap());
21 }
22
23 descriptions
24 }
25}
26
27fn find_attached_description(node: &LuaSyntaxNode) -> Option<LuaSyntaxNode> {
28 let mut prev_sibling = node.prev_sibling_or_token();
29 let mut meet_end_of_line = false;
30 for _ in 0..=5 {
31 prev_sibling.as_ref()?;
32
33 if let Some(sibling) = &prev_sibling {
34 match sibling.kind() {
35 LuaKind::Token(
36 LuaTokenKind::TkWhitespace
37 | LuaTokenKind::TkDocContinue
38 | LuaTokenKind::TkDocStart,
39 ) => {}
40 LuaKind::Token(LuaTokenKind::TkEndOfLine) => {
41 if meet_end_of_line {
42 return None;
43 }
44 meet_end_of_line = true;
45 }
46 LuaKind::Syntax(LuaSyntaxKind::DocDescription) => {
47 let description_node = sibling.clone().into_node()?;
48 if !check_is_inline_description(&description_node).unwrap_or(false) {
49 return Some(description_node);
50 }
51 return None;
52 }
53 _ => {
54 return None;
55 }
56 }
57 }
58 prev_sibling = prev_sibling.unwrap().prev_sibling_or_token();
59 }
60
61 None
62}
63
64fn check_is_inline_description(node: &LuaSyntaxNode) -> Option<bool> {
65 let mut prev_sibling = node.prev_sibling_or_token();
66 for _ in 0..=3 {
67 prev_sibling.as_ref()?;
68
69 if let Some(sibling) = &prev_sibling {
70 match sibling.kind() {
71 LuaKind::Token(LuaTokenKind::TkWhitespace | LuaTokenKind::TkDocContinue) => {}
72 LuaKind::Token(LuaTokenKind::TkEndOfLine | LuaTokenKind::TkNormalStart) => {
73 return Some(false);
74 }
75 _ => {
76 return Some(true);
77 }
78 }
79 }
80 prev_sibling = prev_sibling.unwrap().prev_sibling_or_token();
81 }
82
83 Some(false)
84}
85
86fn find_inline_description(node: &LuaSyntaxNode) -> Option<LuaSyntaxNode> {
87 let mut next_sibling = node.next_sibling_or_token();
88 for _ in 0..=3 {
89 next_sibling.as_ref()?;
90
91 if let Some(sibling) = &next_sibling {
92 match sibling.kind() {
93 LuaKind::Token(LuaTokenKind::TkWhitespace) => {}
94 LuaKind::Syntax(LuaSyntaxKind::DocDescription) => {
95 return sibling.clone().into_node();
96 }
97 _ => {
98 return None;
99 }
100 }
101 }
102 next_sibling = next_sibling.unwrap().next_sibling_or_token();
103 }
104
105 None
106}