emmylua_parser/syntax/node/doc/
description.rs1use crate::{LuaAstNode, LuaDocDetailToken, LuaSyntaxKind, LuaSyntaxNode, LuaTokenKind};
2
3#[allow(unused)]
4pub trait LuaDocDescriptionOwner: LuaAstNode {
5 fn get_description(&self) -> Option<LuaDocDescription> {
6 self.child()
7 }
8}
9
10#[allow(unused)]
11pub trait LuaDocDetailOwner: LuaAstNode {
12 fn get_detail(&self) -> Option<LuaDocDetailToken> {
13 self.token()
14 }
15
16 fn get_detail_text(&self) -> Option<String> {
17 self.get_detail().map(|it| it.get_detail().to_string())
18 }
19}
20
21#[derive(Debug, Clone, PartialEq, Eq, Hash)]
22pub struct LuaDocDescription {
23 syntax: LuaSyntaxNode,
24}
25
26impl LuaAstNode for LuaDocDescription {
27 fn syntax(&self) -> &LuaSyntaxNode {
28 &self.syntax
29 }
30
31 fn can_cast(kind: LuaSyntaxKind) -> bool
32 where
33 Self: Sized,
34 {
35 kind == LuaSyntaxKind::DocDescription
36 }
37
38 fn cast(syntax: LuaSyntaxNode) -> Option<Self>
39 where
40 Self: Sized,
41 {
42 if syntax.kind() == LuaSyntaxKind::DocDescription.into() {
43 Some(Self { syntax })
44 } else {
45 None
46 }
47 }
48}
49
50impl LuaDocDetailOwner for LuaDocDescription {}
51
52impl LuaDocDescription {
53 pub fn get_description_text(&self) -> String {
54 let mut text = String::new();
55 for token in self
56 .syntax()
57 .children_with_tokens()
58 .filter_map(|it| it.into_token())
59 {
60 match token.kind().into() {
61 LuaTokenKind::TkDocDetail => {
62 text.push_str(token.text());
63 }
64 LuaTokenKind::TkEndOfLine => {
65 text.push('\n');
66 }
67 LuaTokenKind::TkNormalStart | LuaTokenKind::TkDocContinue => {
68 let mut white_space_count = 0;
69 let mut start_text_chars = token.text().chars();
70 while let Some(c) = start_text_chars.next() {
71 if c == ' ' {
72 white_space_count += 1;
73 } else if c == '\t' {
74 white_space_count += 4;
75 }
76 }
77
78 if white_space_count > 0 {
79 let white_space = " ".repeat(white_space_count);
80 text.push_str(&white_space);
81 }
82 }
83 _ => {}
84 }
85 }
86
87 text
88 }
89}