1use serde::{Deserialize, Serialize};
2
3#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)]
4#[serde(deny_unknown_fields, tag = "syntax")]
5pub enum Syntax {
6 #[serde(rename = "ecmascript")]
8 Es(EsSyntax),
9 #[cfg(feature = "typescript")]
11 #[cfg_attr(docsrs, doc(cfg(feature = "typescript")))]
12 #[serde(rename = "typescript")]
13 Typescript(TsSyntax),
14}
15
16impl Default for Syntax {
17 fn default() -> Self {
18 Syntax::Es(Default::default())
19 }
20}
21
22impl Syntax {
23 pub fn auto_accessors(self) -> bool {
24 match self {
25 Syntax::Es(EsSyntax {
26 auto_accessors: true,
27 ..
28 }) => true,
29 #[cfg(feature = "typescript")]
30 Syntax::Typescript(_) => true,
31 _ => false,
32 }
33 }
34
35 pub fn import_attributes(self) -> bool {
36 true
37 }
38
39 pub fn jsx(self) -> bool {
41 match self {
42 Syntax::Es(EsSyntax { jsx: true, .. }) => true,
43 #[cfg(feature = "typescript")]
44 Syntax::Typescript(TsSyntax { tsx: true, .. }) => true,
45 _ => false,
46 }
47 }
48
49 pub fn fn_bind(self) -> bool {
50 matches!(self, Syntax::Es(EsSyntax { fn_bind: true, .. }))
51 }
52
53 pub fn decorators(self) -> bool {
54 match self {
55 Syntax::Es(EsSyntax {
56 decorators: true, ..
57 }) => true,
58 #[cfg(feature = "typescript")]
59 Syntax::Typescript(TsSyntax {
60 decorators: true, ..
61 }) => true,
62 _ => false,
63 }
64 }
65
66 pub fn decorators_before_export(self) -> bool {
67 match self {
68 Syntax::Es(EsSyntax {
69 decorators_before_export: true,
70 ..
71 }) => true,
72 #[cfg(feature = "typescript")]
73 Syntax::Typescript(..) => true,
74 _ => false,
75 }
76 }
77
78 #[cfg(not(feature = "typescript"))]
80 pub const fn typescript(self) -> bool {
81 false
82 }
83
84 #[cfg(feature = "typescript")]
86 pub const fn typescript(self) -> bool {
87 matches!(self, Syntax::Typescript(..))
88 }
89
90 pub fn export_default_from(self) -> bool {
91 matches!(
92 self,
93 Syntax::Es(EsSyntax {
94 export_default_from: true,
95 ..
96 })
97 )
98 }
99
100 pub fn dts(self) -> bool {
101 match self {
102 #[cfg(feature = "typescript")]
103 Syntax::Typescript(t) => t.dts,
104 _ => false,
105 }
106 }
107
108 pub fn allow_super_outside_method(self) -> bool {
109 match self {
110 Syntax::Es(EsSyntax {
111 allow_super_outside_method,
112 ..
113 }) => allow_super_outside_method,
114 #[cfg(feature = "typescript")]
115 Syntax::Typescript(_) => true,
116 }
117 }
118
119 pub fn allow_return_outside_function(self) -> bool {
120 match self {
121 Syntax::Es(EsSyntax {
122 allow_return_outside_function,
123 ..
124 }) => allow_return_outside_function,
125 #[cfg(feature = "typescript")]
126 Syntax::Typescript(_) => false,
127 }
128 }
129
130 pub fn early_errors(self) -> bool {
131 match self {
132 #[cfg(feature = "typescript")]
133 Syntax::Typescript(t) => !t.no_early_errors,
134 Syntax::Es(..) => true,
135 }
136 }
137
138 pub fn disallow_ambiguous_jsx_like(self) -> bool {
139 match self {
140 #[cfg(feature = "typescript")]
141 Syntax::Typescript(t) => t.disallow_ambiguous_jsx_like,
142 _ => false,
143 }
144 }
145
146 pub fn explicit_resource_management(&self) -> bool {
147 match self {
148 Syntax::Es(EsSyntax {
149 explicit_resource_management: using_decl,
150 ..
151 }) => *using_decl,
152 #[cfg(feature = "typescript")]
153 Syntax::Typescript(_) => true,
154 }
155 }
156
157 pub fn into_flags(self) -> SyntaxFlags {
158 match self {
159 Syntax::Es(es) => es.into_flags(),
160 #[cfg(feature = "typescript")]
161 Syntax::Typescript(ts) => ts.into_flags(),
162 }
163 }
164}
165
166#[derive(Debug, Clone, Copy, PartialEq, Eq, Default, Serialize, Deserialize)]
167#[serde(rename_all = "camelCase")]
168pub struct TsSyntax {
169 #[serde(default)]
170 pub tsx: bool,
171
172 #[serde(default)]
173 pub decorators: bool,
174
175 #[serde(skip, default)]
177 pub dts: bool,
178
179 #[serde(skip, default)]
180 pub no_early_errors: bool,
181
182 #[serde(skip, default)]
188 pub disallow_ambiguous_jsx_like: bool,
189}
190
191impl TsSyntax {
192 fn into_flags(self) -> SyntaxFlags {
193 let mut flags = SyntaxFlags::TS
194 .union(SyntaxFlags::AUTO_ACCESSORS)
195 .union(SyntaxFlags::IMPORT_ATTRIBUTES)
196 .union(SyntaxFlags::DECORATORS_BEFORE_EXPORT)
197 .union(SyntaxFlags::ALLOW_SUPER_OUTSIDE_METHOD)
198 .union(SyntaxFlags::EXPLICIT_RESOURCE_MANAGEMENT);
199
200 if self.tsx {
201 flags |= SyntaxFlags::JSX;
202 }
203 if self.decorators {
204 flags |= SyntaxFlags::DECORATORS;
205 }
206 if self.dts {
207 flags |= SyntaxFlags::DTS;
208 }
209 if self.no_early_errors {
210 flags |= SyntaxFlags::NO_EARLY_ERRORS;
211 }
212 if self.disallow_ambiguous_jsx_like {
213 flags |= SyntaxFlags::DISALLOW_AMBIGUOUS_JSX_LIKE;
214 }
215 flags
216 }
217}
218
219#[derive(Debug, Clone, Copy, PartialEq, Eq, Default, Serialize, Deserialize)]
220#[serde(rename_all = "camelCase")]
221pub struct EsSyntax {
222 #[serde(default)]
223 pub jsx: bool,
224
225 #[serde(rename = "functionBind")]
227 #[serde(default)]
228 pub fn_bind: bool,
229
230 #[serde(default)]
232 pub decorators: bool,
233
234 #[serde(rename = "decoratorsBeforeExport")]
238 #[serde(default)]
239 pub decorators_before_export: bool,
240
241 #[serde(default)]
242 pub export_default_from: bool,
243
244 #[serde(default, alias = "importAssertions")]
247 pub import_attributes: bool,
248
249 #[serde(default, rename = "allowSuperOutsideMethod")]
250 pub allow_super_outside_method: bool,
251
252 #[serde(default, rename = "allowReturnOutsideFunction")]
253 pub allow_return_outside_function: bool,
254
255 #[serde(default)]
256 pub auto_accessors: bool,
257
258 #[serde(default)]
259 pub explicit_resource_management: bool,
260}
261
262impl EsSyntax {
263 fn into_flags(self) -> SyntaxFlags {
264 let mut flags = SyntaxFlags::empty();
265 if self.jsx {
266 flags |= SyntaxFlags::JSX;
267 }
268 if self.fn_bind {
269 flags |= SyntaxFlags::FN_BIND;
270 }
271 if self.decorators {
272 flags |= SyntaxFlags::DECORATORS;
273 }
274 if self.decorators_before_export {
275 flags |= SyntaxFlags::DECORATORS_BEFORE_EXPORT;
276 }
277 if self.export_default_from {
278 flags |= SyntaxFlags::EXPORT_DEFAULT_FROM;
279 }
280 if self.import_attributes {
281 flags |= SyntaxFlags::IMPORT_ATTRIBUTES;
282 }
283 if self.allow_super_outside_method {
284 flags |= SyntaxFlags::ALLOW_SUPER_OUTSIDE_METHOD;
285 }
286 if self.allow_return_outside_function {
287 flags |= SyntaxFlags::ALLOW_RETURN_OUTSIDE_FUNCTION;
288 }
289 if self.auto_accessors {
290 flags |= SyntaxFlags::AUTO_ACCESSORS;
291 }
292 if self.explicit_resource_management {
293 flags |= SyntaxFlags::EXPLICIT_RESOURCE_MANAGEMENT;
294 }
295 flags
296 }
297}
298
299impl SyntaxFlags {
300 #[inline(always)]
301 pub const fn auto_accessors(&self) -> bool {
302 self.contains(Self::AUTO_ACCESSORS)
303 }
304
305 #[inline(always)]
306 pub const fn import_attributes(&self) -> bool {
307 true
308 }
309
310 #[inline(always)]
312 pub const fn jsx(&self) -> bool {
313 self.contains(SyntaxFlags::JSX)
314 }
315
316 #[inline(always)]
317 pub const fn fn_bind(&self) -> bool {
318 self.contains(SyntaxFlags::FN_BIND)
319 }
320
321 #[inline(always)]
322 pub const fn decorators(&self) -> bool {
323 self.contains(SyntaxFlags::DECORATORS)
324 }
325
326 #[inline(always)]
327 pub const fn decorators_before_export(&self) -> bool {
328 self.contains(SyntaxFlags::DECORATORS_BEFORE_EXPORT)
329 }
330
331 #[cfg(not(feature = "typescript"))]
333 #[inline(always)]
334 pub const fn typescript(&self) -> bool {
335 false
336 }
337
338 #[cfg(feature = "typescript")]
340 #[inline(always)]
341 pub const fn typescript(&self) -> bool {
342 self.contains(SyntaxFlags::TS)
343 }
344
345 #[inline(always)]
346 pub const fn export_default_from(&self) -> bool {
347 self.contains(SyntaxFlags::EXPORT_DEFAULT_FROM)
348 }
349
350 #[inline(always)]
351 pub const fn dts(&self) -> bool {
352 self.contains(SyntaxFlags::DTS)
353 }
354
355 #[inline(always)]
356 pub const fn allow_super_outside_method(&self) -> bool {
357 self.contains(SyntaxFlags::ALLOW_SUPER_OUTSIDE_METHOD)
358 }
359
360 #[inline(always)]
361 pub const fn allow_return_outside_function(&self) -> bool {
362 self.contains(SyntaxFlags::ALLOW_RETURN_OUTSIDE_FUNCTION)
363 }
364
365 #[inline(always)]
366 pub const fn early_errors(&self) -> bool {
367 !self.contains(SyntaxFlags::NO_EARLY_ERRORS)
368 }
369
370 #[inline(always)]
371 pub const fn disallow_ambiguous_jsx_like(&self) -> bool {
372 self.contains(SyntaxFlags::TS.union(SyntaxFlags::DISALLOW_AMBIGUOUS_JSX_LIKE))
373 }
374
375 #[inline(always)]
376 pub const fn explicit_resource_management(&self) -> bool {
377 self.contains(SyntaxFlags::EXPLICIT_RESOURCE_MANAGEMENT)
378 }
379}
380
381bitflags::bitflags! {
382 #[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
383 pub struct SyntaxFlags: u16 {
384 const JSX = 1 << 0;
385 const FN_BIND = 1 << 1;
386 const DECORATORS = 1 << 2;
387 const DECORATORS_BEFORE_EXPORT = 1 << 3;
388 const EXPORT_DEFAULT_FROM = 1 << 4;
389 const IMPORT_ATTRIBUTES = 1 << 5;
390 const ALLOW_SUPER_OUTSIDE_METHOD = 1 << 6;
391 const ALLOW_RETURN_OUTSIDE_FUNCTION = 1 << 7;
392 const AUTO_ACCESSORS = 1 << 8;
393 const EXPLICIT_RESOURCE_MANAGEMENT = 1 << 9;
394 const DTS = 1 << 10;
395 const NO_EARLY_ERRORS = 1 << 11;
396 const DISALLOW_AMBIGUOUS_JSX_LIKE = 1 << 12;
397 const TS = 1 << 13;
398 }
399}