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 Some(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        if prev_sibling.is_none() {
37            return None;
38        }
39
40        if let Some(sibling) = &prev_sibling {
41            match sibling.kind() {
42                LuaKind::Token(LuaTokenKind::TkWhitespace) => {}
43                LuaKind::Token(LuaTokenKind::TkEndOfLine) => {
44                    if meet_end_of_line {
45                        return None;
46                    }
47                    meet_end_of_line = true;
48                }
49                LuaKind::Syntax(LuaSyntaxKind::Comment) => return sibling.clone().into_node(),
50                _ => {
51                    return None;
52                }
53            }
54        }
55        prev_sibling = prev_sibling.unwrap().prev_sibling_or_token();
56    }
57
58    None
59}
60
61fn find_inline_comment(node: &LuaSyntaxNode) -> Option<LuaSyntaxNode> {
62    let mut next_sibling = node.next_sibling_or_token();
63    for _ in 0..=3 {
64        if next_sibling.is_none() {
65            return None;
66        }
67
68        if let Some(sibling) = &next_sibling {
69            match sibling.kind() {
70                LuaKind::Token(
71                    LuaTokenKind::TkWhitespace | LuaTokenKind::TkComma | LuaTokenKind::TkSemicolon,
72                ) => {}
73                LuaKind::Syntax(LuaSyntaxKind::Comment) => return sibling.clone().into_node(),
74                _ => {
75                    return None;
76                }
77            }
78        }
79        next_sibling = next_sibling.unwrap().next_sibling_or_token();
80    }
81
82    None
83}