swc_ecma_codegen/text_writer/
semicolon.rs1use swc_common::{BytePos, Span, DUMMY_SP};
2
3use super::{Result, WriteJs};
4
5pub fn omit_trailing_semi<W: WriteJs>(w: W) -> impl WriteJs {
6 OmitTrailingSemi {
7 inner: w,
8 pending_semi: None,
9 }
10}
11
12#[derive(Debug, Clone)]
13struct OmitTrailingSemi<W: WriteJs> {
14 inner: W,
15 pending_semi: Option<Span>,
16}
17
18macro_rules! with_semi {
19 (
20 $fn_name:ident
21 (
22 $(
23 $arg_name:ident
24 :
25 $arg_ty:ty
26 ),*
27 )
28 ) => {
29 fn $fn_name(&mut self, $($arg_name: $arg_ty),* ) -> Result {
30 self.commit_pending_semi()?;
31
32 self.inner.$fn_name( $($arg_name),* )
33 }
34 };
35}
36
37impl<W: WriteJs> WriteJs for OmitTrailingSemi<W> {
38 with_semi!(increase_indent());
39
40 with_semi!(decrease_indent());
41
42 with_semi!(write_space());
43
44 with_semi!(write_comment(s: &str));
45
46 with_semi!(write_keyword(span: Option<Span>, s: &'static str));
47
48 with_semi!(write_operator(span: Option<Span>, s: &str));
49
50 with_semi!(write_param(s: &str));
51
52 with_semi!(write_property(s: &str));
53
54 with_semi!(write_line());
55
56 with_semi!(write_lit(span: Span, s: &str));
57
58 with_semi!(write_str_lit(span: Span, s: &str));
59
60 with_semi!(write_str(s: &str));
61
62 with_semi!(write_symbol(span: Span, s: &str));
63
64 fn write_semi(&mut self, span: Option<Span>) -> Result {
65 self.pending_semi = Some(span.unwrap_or(DUMMY_SP));
66 Ok(())
67 }
68
69 fn write_punct(&mut self, span: Option<Span>, s: &'static str) -> Result {
70 let bytes = s.as_bytes();
71 if bytes.len() == 1 {
72 let first = *unsafe { bytes.get_unchecked(0) };
73 static PUNCT_TABLE: [bool; 256] = {
74 let mut table = [false; 256];
75 table[b'"' as usize] = true;
76 table[b'\'' as usize] = true;
77 table[b'[' as usize] = true;
78 table[b'!' as usize] = true;
79 table[b'/' as usize] = true;
80 table[b'{' as usize] = true;
81 table[b'(' as usize] = true;
82 table[b'~' as usize] = true;
83 table[b'-' as usize] = true;
84 table[b'+' as usize] = true;
85 table[b'#' as usize] = true;
86 table[b'`' as usize] = true;
87 table[b'*' as usize] = true;
88 table
89 };
90 if PUNCT_TABLE[first as usize] {
91 self.commit_pending_semi()?;
92 return self.inner.write_punct(span, s);
93 }
94 }
95 self.pending_semi = None;
96 self.inner.write_punct(span, s)
97 }
98
99 #[inline]
100 fn care_about_srcmap(&self) -> bool {
101 self.inner.care_about_srcmap()
102 }
103
104 #[inline]
105 fn add_srcmap(&mut self, pos: BytePos) -> Result {
106 self.inner.add_srcmap(pos)
107 }
108
109 fn commit_pending_semi(&mut self) -> Result {
110 if let Some(span) = self.pending_semi {
111 self.inner.write_semi(Some(span))?;
112 self.pending_semi = None;
113 }
114 Ok(())
115 }
116
117 #[inline(always)]
118 fn can_ignore_invalid_unicodes(&mut self) -> bool {
119 self.inner.can_ignore_invalid_unicodes()
120 }
121}