emmylua_parser/syntax/
comment_trait.rs

1use crate::{
2    kind::{LuaSyntaxKind, LuaTokenKind},
3    LuaKind,
4};
5
6use super::{node::LuaComment, traits::LuaAstNode, LuaSyntaxNode};
7
8#[allow(unused)]
9pub trait LuaCommentOwner: LuaAstNode {
10    fn get_comments(&self) -> Vec<LuaComment> {
11        let mut comments = vec![];
12        if let Some(attached_comment) = find_attached_comment(self.syntax()) {
13            comments.push(LuaComment::cast(attached_comment).unwrap());
14        }
15
16        if let Some(inline_comment) = find_inline_comment(self.syntax()) {
17            comments.push(LuaComment::cast(inline_comment).unwrap());
18        }
19
20        comments
21    }
22
23    fn get_left_comment(&self) -> Option<LuaComment> {
24        if let Some(attached_comment) = find_attached_comment(self.syntax()) {
25            return LuaComment::cast(attached_comment);
26        }
27
28        None
29    }
30}
31
32fn find_attached_comment(node: &LuaSyntaxNode) -> Option<LuaSyntaxNode> {
33    let mut prev_sibling = node.prev_sibling_or_token();
34    let mut meet_end_of_line = false;
35    for _ in 0..=2 {
36        prev_sibling.as_ref()?;
37
38        if let Some(sibling) = &prev_sibling {
39            match sibling.kind() {
40                LuaKind::Token(LuaTokenKind::TkWhitespace) => {}
41                LuaKind::Token(LuaTokenKind::TkEndOfLine) => {
42                    if meet_end_of_line {
43                        return None;
44                    }
45                    meet_end_of_line = true;
46                }
47                LuaKind::Syntax(LuaSyntaxKind::Comment) => return sibling.clone().into_node(),
48                _ => {
49                    return None;
50                }
51            }
52        }
53        prev_sibling = prev_sibling.unwrap().prev_sibling_or_token();
54    }
55
56    None
57}
58
59fn find_inline_comment(node: &LuaSyntaxNode) -> Option<LuaSyntaxNode> {
60    let mut next_sibling = node.next_sibling_or_token();
61    for _ in 0..=3 {
62        next_sibling.as_ref()?;
63
64        if let Some(sibling) = &next_sibling {
65            match sibling.kind() {
66                LuaKind::Token(
67                    LuaTokenKind::TkWhitespace | LuaTokenKind::TkComma | LuaTokenKind::TkSemicolon,
68                ) => {}
69                LuaKind::Syntax(LuaSyntaxKind::Comment) => return sibling.clone().into_node(),
70                _ => {
71                    return None;
72                }
73            }
74        }
75        next_sibling = next_sibling.unwrap().next_sibling_or_token();
76    }
77
78    None
79}