#![cfg_attr(test, feature(test))]
#![deny(unused)]
pub use self::{
lexer::input::{Input, StringInput},
parser::*,
};
use serde::{Deserialize, Serialize};
use swc_common::Span;
#[macro_use]
mod macros;
pub mod error;
pub mod lexer;
mod parser;
pub mod token;
#[derive(Debug, Clone, Copy, Deserialize, Serialize)]
#[serde(deny_unknown_fields, tag = "syntax")]
pub enum Syntax {
#[serde(rename = "ecmascript")]
Es(EsConfig),
#[serde(rename = "typescript")]
Typescript(TsConfig),
}
impl Default for Syntax {
fn default() -> Self {
Syntax::Es(Default::default())
}
}
impl Syntax {
pub fn jsx(self) -> bool {
match self {
Syntax::Es(EsConfig { jsx: true, .. })
| Syntax::Typescript(TsConfig { tsx: true, .. }) => true,
_ => false,
}
}
pub fn optional_chaining(self) -> bool {
true
}
pub fn dynamic_import(self) -> bool {
match self {
Syntax::Es(EsConfig {
dynamic_import: true,
..
})
| Syntax::Typescript(TsConfig {
dynamic_import: true,
..
}) => true,
_ => false,
}
}
pub fn fn_bind(self) -> bool {
match self {
Syntax::Es(EsConfig { fn_bind: true, .. }) => true,
_ => false,
}
}
pub fn num_sep(self) -> bool {
true
}
pub fn decorators(self) -> bool {
match self {
Syntax::Es(EsConfig {
decorators: true, ..
})
| Syntax::Typescript(TsConfig {
decorators: true, ..
}) => true,
_ => false,
}
}
pub fn class_private_methods(self) -> bool {
true
}
pub fn class_private_props(self) -> bool {
match self {
Syntax::Es(EsConfig {
class_private_props: true,
..
})
| Syntax::Typescript(..) => true,
_ => false,
}
}
pub fn class_props(self) -> bool {
true
}
pub fn decorators_before_export(self) -> bool {
match self {
Syntax::Es(EsConfig {
decorators_before_export: true,
..
})
| Syntax::Typescript(..) => true,
_ => false,
}
}
pub fn typescript(self) -> bool {
match self {
Syntax::Typescript(..) => true,
_ => false,
}
}
pub fn export_default_from(self) -> bool {
match self {
Syntax::Es(EsConfig {
export_default_from: true,
..
}) => true,
_ => false,
}
}
pub fn export_namespace_from(self) -> bool {
match self {
Syntax::Es(EsConfig {
export_namespace_from: true,
..
})
| Syntax::Typescript(..) => true,
_ => false,
}
}
pub fn nullish_coalescing(self) -> bool {
true
}
pub fn import_meta(self) -> bool {
match self {
Syntax::Es(EsConfig {
import_meta: true, ..
})
| Syntax::Typescript(..) => true,
_ => false,
}
}
pub fn top_level_await(self) -> bool {
match self {
Syntax::Es(EsConfig {
top_level_await: true,
..
})
| Syntax::Typescript(..) => true,
_ => false,
}
}
pub fn dts(self) -> bool {
match self {
Syntax::Typescript(t) => t.dts,
_ => false,
}
}
pub(crate) fn early_errors(self) -> bool {
match self {
Syntax::Typescript(t) => !t.no_early_errors,
Syntax::Es(..) => true,
}
}
}
#[derive(Debug, Clone, Copy, Default, Serialize, Deserialize)]
#[serde(deny_unknown_fields, rename_all = "camelCase")]
pub struct TsConfig {
#[serde(default)]
pub tsx: bool,
#[serde(default)]
pub decorators: bool,
#[serde(default)]
pub dynamic_import: bool,
#[serde(skip, default)]
pub dts: bool,
#[serde(skip, default)]
pub no_early_errors: bool,
}
#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialOrd, Ord, PartialEq, Eq)]
pub enum JscTarget {
#[serde(rename = "es3")]
Es3,
#[serde(rename = "es5")]
Es5,
#[serde(rename = "es2015")]
Es2015,
#[serde(rename = "es2016")]
Es2016,
#[serde(rename = "es2017")]
Es2017,
#[serde(rename = "es2018")]
Es2018,
#[serde(rename = "es2019")]
Es2019,
#[serde(rename = "es2020")]
Es2020,
}
impl Default for JscTarget {
fn default() -> Self {
JscTarget::Es5
}
}
#[derive(Debug, Clone, Copy, Default, Serialize, Deserialize)]
#[serde(deny_unknown_fields, rename_all = "camelCase")]
pub struct EsConfig {
#[serde(default)]
pub jsx: bool,
#[serde(rename = "numericSeparator")]
#[serde(default)]
pub num_sep: bool,
#[serde(rename = "classPrivateProperty")]
#[serde(default)]
pub class_private_props: bool,
#[serde(rename = "privateMethod")]
#[serde(default)]
pub class_private_methods: bool,
#[serde(rename = "classProperty")]
#[serde(default)]
pub class_props: bool,
#[serde(rename = "functionBind")]
#[serde(default)]
pub fn_bind: bool,
#[serde(default)]
pub decorators: bool,
#[serde(rename = "decoratorsBeforeExport")]
#[serde(default)]
pub decorators_before_export: bool,
#[serde(default)]
pub export_default_from: bool,
#[serde(default)]
pub export_namespace_from: bool,
#[serde(default)]
pub dynamic_import: bool,
#[serde(default)]
pub nullish_coalescing: bool,
#[serde(default)]
pub optional_chaining: bool,
#[serde(default)]
pub import_meta: bool,
#[serde(default)]
pub top_level_await: bool,
}
#[derive(Debug, Clone, Copy, Default)]
pub struct Context {
module: bool,
strict: bool,
include_in_expr: bool,
in_async: bool,
in_generator: bool,
is_continue_allowed: bool,
is_break_allowed: bool,
in_type: bool,
in_declare: bool,
span_of_fn_name: Option<Span>,
in_cond_expr: bool,
in_function: bool,
in_parameters: bool,
in_method: bool,
in_class_prop: bool,
in_property_name: bool,
in_forced_jsx_context: bool,
in_case_cond: bool,
}
#[cfg(test)]
fn with_test_sess<F, Ret>(src: &str, f: F) -> Result<Ret, ::testing::StdErr>
where
F: FnOnce(&swc_common::errors::Handler, StringInput<'_>) -> Result<Ret, ()>,
{
use swc_common::FileName;
::testing::run_test(false, |cm, handler| {
let fm = cm.new_source_file(FileName::Real("testing".into()), src.into());
f(handler, (&*fm).into())
})
}