1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
//! Trivias such as comments

use std::collections::BTreeMap;

use oxc_span::Span;

/// A vec of trivias from the lexer, tupled by (span.start, span.end).
pub type Trivias = Vec<(u32, u32, CommentKind)>;

/// Trivias such as comments
///
/// Trivia (called that because it's trivial) represent the parts of the source text that are largely insignificant for normal understanding of the code.
/// For example: whitespace, comments, and even conflict markers.
#[derive(Debug, Default)]
pub struct TriviasMap {
    /// Keyed by span.start
    comments: BTreeMap<u32, Comment>,
}

impl From<Trivias> for TriviasMap {
    fn from(trivias: Trivias) -> Self {
        Self { comments: trivias.iter().map(|t| (t.0, Comment::new(t.1, t.2))).collect() }
    }
}

/// Single or multiline comment
#[derive(Debug, Clone, Copy)]
#[allow(unused)]
pub struct Comment {
    kind: CommentKind,
    end: u32,
}

#[derive(Debug, Clone, Copy, Eq, PartialEq)]
pub enum CommentKind {
    SingleLine,
    MultiLine,
}

impl Comment {
    pub fn new(end: u32, kind: CommentKind) -> Self {
        Self { kind, end }
    }

    pub fn end(self) -> u32 {
        self.end
    }

    pub fn is_single_line(self) -> bool {
        matches!(self.kind, CommentKind::SingleLine)
    }

    pub fn is_multi_line(self) -> bool {
        matches!(self.kind, CommentKind::MultiLine)
    }
}

impl TriviasMap {
    pub fn comments(&self) -> &BTreeMap<u32, Comment> {
        &self.comments
    }

    pub fn has_comments_between(&self, span: Span) -> bool {
        self.comments.range(span.start..span.end).count() > 0
    }

    pub fn add_single_line_comment(&mut self, span: Span) {
        let comment = Comment::new(span.end, CommentKind::SingleLine);
        self.comments.insert(span.start, comment);
    }

    pub fn add_multi_line_comment(&mut self, span: Span) {
        let comment = Comment::new(span.end, CommentKind::MultiLine);
        self.comments.insert(span.start, comment);
    }
}