swc_ecma_parser/lexer/
capturing.rs

1use std::mem;
2
3use swc_ecma_lexer::common::syntax::SyntaxFlags;
4
5use crate::{input::Tokens, lexer::token::TokenAndSpan};
6
7#[derive(Debug)]
8pub struct Capturing<I> {
9    inner: I,
10    captured: Vec<TokenAndSpan>,
11}
12
13pub struct CapturingCheckpoint<I: swc_ecma_lexer::common::input::Tokens<TokenAndSpan>> {
14    pos: usize,
15    inner: I::Checkpoint,
16}
17
18impl<I: Clone> Clone for Capturing<I> {
19    fn clone(&self) -> Self {
20        Capturing {
21            inner: self.inner.clone(),
22            captured: self.captured.clone(),
23        }
24    }
25}
26
27impl<I> Capturing<I> {
28    pub fn new(input: I) -> Self {
29        Capturing {
30            inner: input,
31            captured: Default::default(),
32        }
33    }
34
35    pub fn tokens(&self) -> &[TokenAndSpan] {
36        &self.captured
37    }
38
39    /// Take captured tokens
40    pub fn take(&mut self) -> Vec<TokenAndSpan> {
41        mem::take(&mut self.captured)
42    }
43
44    fn capture(&mut self, ts: TokenAndSpan) {
45        let v = &mut self.captured;
46
47        // remove tokens that could change due to backtracing
48        while let Some(last) = v.last() {
49            if last.span.lo >= ts.span.lo {
50                v.pop();
51            } else {
52                break;
53            }
54        }
55
56        v.push(ts);
57    }
58}
59
60impl<I: Iterator<Item = TokenAndSpan>> Iterator for Capturing<I> {
61    type Item = TokenAndSpan;
62
63    fn next(&mut self) -> Option<Self::Item> {
64        let next = self.inner.next();
65
66        match next {
67            Some(ts) => {
68                self.capture(ts);
69                Some(ts)
70            }
71            None => None,
72        }
73    }
74}
75
76impl<I: swc_ecma_lexer::common::input::Tokens<TokenAndSpan>>
77    swc_ecma_lexer::common::input::Tokens<TokenAndSpan> for Capturing<I>
78{
79    type Checkpoint = CapturingCheckpoint<I>;
80
81    fn checkpoint_save(&self) -> Self::Checkpoint {
82        Self::Checkpoint {
83            pos: self.captured.len(),
84            inner: self.inner.checkpoint_save(),
85        }
86    }
87
88    fn checkpoint_load(&mut self, checkpoint: Self::Checkpoint) {
89        self.captured.truncate(checkpoint.pos);
90        self.inner.checkpoint_load(checkpoint.inner);
91    }
92
93    fn set_ctx(&mut self, ctx: swc_ecma_lexer::common::context::Context) {
94        self.inner.set_ctx(ctx);
95    }
96
97    fn ctx(&self) -> swc_ecma_lexer::common::context::Context {
98        self.inner.ctx()
99    }
100
101    fn ctx_mut(&mut self) -> &mut swc_ecma_lexer::common::context::Context {
102        self.inner.ctx_mut()
103    }
104
105    fn syntax(&self) -> SyntaxFlags {
106        self.inner.syntax()
107    }
108
109    fn target(&self) -> swc_ecma_ast::EsVersion {
110        self.inner.target()
111    }
112
113    fn set_expr_allowed(&mut self, allow: bool) {
114        self.inner.set_expr_allowed(allow);
115    }
116
117    fn set_next_regexp(&mut self, start: Option<swc_common::BytePos>) {
118        self.inner.set_next_regexp(start);
119    }
120
121    fn token_context(&self) -> &swc_ecma_lexer::lexer::TokenContexts {
122        self.inner.token_context()
123    }
124
125    fn token_context_mut(&mut self) -> &mut swc_ecma_lexer::lexer::TokenContexts {
126        self.inner.token_context_mut()
127    }
128
129    fn set_token_context(&mut self, c: swc_ecma_lexer::lexer::TokenContexts) {
130        self.inner.set_token_context(c);
131    }
132
133    fn add_error(&mut self, error: swc_ecma_lexer::error::Error) {
134        self.inner.add_error(error);
135    }
136
137    fn add_module_mode_error(&mut self, error: swc_ecma_lexer::error::Error) {
138        self.inner.add_module_mode_error(error);
139    }
140
141    fn end_pos(&self) -> swc_common::BytePos {
142        self.inner.end_pos()
143    }
144
145    fn take_errors(&mut self) -> Vec<swc_ecma_lexer::error::Error> {
146        self.inner.take_errors()
147    }
148
149    fn take_script_module_errors(&mut self) -> Vec<swc_ecma_lexer::error::Error> {
150        self.inner.take_script_module_errors()
151    }
152
153    fn update_token_flags(&mut self, f: impl FnOnce(&mut swc_ecma_lexer::lexer::TokenFlags)) {
154        self.inner.update_token_flags(f);
155    }
156
157    fn token_flags(&self) -> swc_ecma_lexer::lexer::TokenFlags {
158        self.inner.token_flags()
159    }
160}
161
162impl<I: Tokens> Tokens for Capturing<I> {
163    fn clone_token_value(&self) -> Option<super::TokenValue> {
164        self.inner.clone_token_value()
165    }
166
167    fn take_token_value(&mut self) -> Option<super::TokenValue> {
168        self.inner.take_token_value()
169    }
170
171    fn get_token_value(&self) -> Option<&super::TokenValue> {
172        self.inner.get_token_value()
173    }
174
175    fn set_token_value(&mut self, token_value: Option<super::TokenValue>) {
176        self.inner.set_token_value(token_value);
177    }
178
179    fn scan_jsx_token(&mut self, allow_multiline_jsx_text: bool) -> TokenAndSpan {
180        self.inner.scan_jsx_token(allow_multiline_jsx_text)
181    }
182
183    fn scan_jsx_open_el_terminal_token(&mut self) -> TokenAndSpan {
184        self.inner.scan_jsx_open_el_terminal_token()
185    }
186
187    fn rescan_jsx_open_el_terminal_token(&mut self, reset: swc_common::BytePos) -> TokenAndSpan {
188        let ts = self.inner.rescan_jsx_open_el_terminal_token(reset);
189        self.capture(ts);
190        ts
191    }
192
193    fn rescan_jsx_token(
194        &mut self,
195        allow_multiline_jsx_text: bool,
196        reset: swc_common::BytePos,
197    ) -> TokenAndSpan {
198        let ts = self.inner.rescan_jsx_token(allow_multiline_jsx_text, reset);
199        self.capture(ts);
200        ts
201    }
202
203    fn scan_jsx_identifier(&mut self, start: swc_common::BytePos) -> TokenAndSpan {
204        let ts = self.inner.scan_jsx_identifier(start);
205        self.capture(ts);
206        ts
207    }
208
209    fn scan_jsx_attribute_value(&mut self) -> TokenAndSpan {
210        let ts = self.inner.scan_jsx_attribute_value();
211        self.capture(ts);
212        ts
213    }
214
215    fn rescan_template_token(
216        &mut self,
217        start: swc_common::BytePos,
218        start_with_back_tick: bool,
219    ) -> TokenAndSpan {
220        let ts = self
221            .inner
222            .rescan_template_token(start, start_with_back_tick);
223        self.capture(ts);
224        ts
225    }
226}