swc_ecma_codegen/
comments.rs

1use swc_atoms::atom;
2use swc_common::comments::Comment;
3
4use super::*;
5
6macro_rules! write_comments {
7    ($e:expr, $prefix_space:expr, $cmts:expr) => {{
8        let cmts = match $cmts {
9            Some(v) => v,
10            None => return Ok(()),
11        };
12
13        for cmt in cmts.iter() {
14            match cmt.kind {
15                CommentKind::Line => {
16                    if $prefix_space && !$e.cfg.minify {
17                        $e.wr.write_comment(" ")?;
18                    }
19
20                    srcmap!($e, cmt, true);
21
22                    $e.wr.write_comment("//")?;
23                    $e.wr.write_comment(&cmt.text)?;
24
25                    srcmap!($e, cmt, false);
26
27                    $e.wr.write_line()?;
28                }
29                CommentKind::Block => {
30                    if $prefix_space && !$e.cfg.minify {
31                        $e.wr.write_comment(" ")?;
32                    }
33
34                    srcmap!($e, cmt, true);
35
36                    $e.wr.write_comment("/*")?;
37                    $e.wr.write_comment(&cmt.text)?;
38
39                    {
40                        let hi = cmt.span_hi();
41                        if !hi.is_dummy() && hi.0 > 2 {
42                            $e.wr.add_srcmap(hi - swc_common::BytePos(2))?;
43                        }
44                    }
45                    $e.wr.write_comment("*/")?;
46
47                    if !$e.cfg.minify {
48                        $e.wr.write_space()?;
49                    }
50                }
51            }
52        }
53
54        return Ok(());
55    }};
56}
57
58impl<W, S: SourceMapper> Emitter<'_, W, S>
59where
60    W: WriteJs,
61    S: SourceMapperExt,
62{
63    pub(super) fn emit_trailing_comments_of_pos(
64        &mut self,
65        pos: BytePos,
66        prefix_space: bool,
67        _is_hi: bool,
68    ) -> Result {
69        let cmts = self.take_trailing_comments_of_pos(pos);
70
71        write_comments!(self, prefix_space, &cmts)
72    }
73
74    pub(super) fn emit_trailing_comments_of_pos_with(
75        &mut self,
76        pos: BytePos,
77        prefix_space: bool,
78        callback: impl FnOnce(&mut Self) -> Result,
79    ) -> Result {
80        let cmts = self.take_trailing_comments_of_pos(pos);
81
82        callback(self)?;
83
84        write_comments!(self, prefix_space, &cmts)
85    }
86
87    fn take_trailing_comments_of_pos(&mut self, pos: BytePos) -> Option<Vec<Comment>> {
88        if pos.is_dummy() {
89            return None;
90        }
91
92        let comments = match self.comments {
93            Some(ref comments) => comments,
94            None => return None,
95        };
96
97        comments.take_trailing(pos)
98    }
99
100    pub(super) fn emit_leading_comments(&mut self, mut pos: BytePos, is_hi: bool) -> Result {
101        if pos.is_dummy() {
102            return Ok(());
103        }
104
105        if pos.is_pure() {
106            write_comments!(
107                self,
108                false,
109                Some(vec![Comment {
110                    kind: CommentKind::Block,
111                    span: DUMMY_SP,
112                    text: atom!("#__PURE__"),
113                }])
114            );
115        }
116
117        let comments = match self.comments {
118            Some(ref comments) => comments,
119            None => return Ok(()),
120        };
121
122        if is_hi {
123            pos = pos - BytePos(1)
124        }
125
126        write_comments!(self, false, comments.take_leading(pos))
127    }
128
129    #[inline(always)]
130    pub(super) fn emit_leading_comments_of_span(&mut self, span: Span, is_hi: bool) -> Result {
131        let pos = if is_hi { span.hi } else { span.lo };
132        self.emit_leading_comments(pos, is_hi)
133    }
134}