Vendor things

This commit is contained in:
John Doty 2024-03-08 11:03:01 -08:00
parent 5deceec006
commit 977e3c17e5
19434 changed files with 10682014 additions and 0 deletions

View file

@ -0,0 +1 @@
{"files":{"Cargo.toml":"82f6412f0c83abe382bc7adb8ee1d841f2ba54fa23b9f477e9a362948b739214","src/class.rs":"2624aaec21e46a459e986bbec5da6f5c280819c714d60d27ba02bad266c9d78c","src/decl.rs":"20238ac98e6b91775fe7b89b3f616e2984926390da56f285a5be22fee30c1385","src/expr.rs":"ed344de2736ca310989a5ae8a1083e95a14a49a2fe91b5d0775a33fcfab7aaca","src/function.rs":"9679ffbe4778dc8861af3a67bcfa9a51fdb530ed18e115fb68c114b16348efdf","src/ident.rs":"42feec81907db73a6150268926ae4d637e9b46e66d059b67bdc1c9738b5dce11","src/jsx.rs":"df2fa33ce85977755e4c99bafd7b67dce6e6f1f4029eea2f7ad27bfaff7ec263","src/lib.rs":"4f112616d9d143106c5d02fabbb512dd0d25e156d80867995575e3b5772cf462","src/list.rs":"f56d7dc7708befd25b2b812f0ff58808e1821649b736d3f1ee16b227a0ef2c5c","src/lit.rs":"20682c07a4b36073bf2bba204d0e272dd35e9ad66bde98358e06edf3001c0423","src/macros.rs":"915a05ca10f2d74e338eb98e665c0f994a932b1bada904108e73a0c393e5067e","src/module.rs":"011305c197569827d722955e1c669ba256e3edd22b36620316b68f30387449f1","src/module_decl.rs":"938589b0f49cf59a261ada93fa6464506a7067e065b7b4e6ed289bcd98eb6f66","src/operators.rs":"c8c946655bc6772e7cc3909e488e5573f6c555da0cde59c6c66b750a0ffed8dc","src/pat.rs":"ab4e47bfb2ad070df2610a9ac12496308bebe95c63bfb075a586c0062212f450","src/prop.rs":"0852cae0e5a207b6f30700af2b54b1cf9ed71c6fbf637014517aec8440d8f858","src/source_map.rs":"b25d5c25b086df6bc95bfc991558c0f45618a5a7d1ce1ae4b179de65a4983970","src/stmt.rs":"b310b2fa1ddd490742fde3040507e952a563eab11a8fc8a945730c071f336ecf","src/typescript.rs":"3d6b619b2596de8820b3050e663367492b438c814fc60605b5e9181f184c4b9c"},"package":"7bc2286cedd688a68f214faa1c19bb5cceab7c9c54d0cbe3273e4c1704e38f69"}

View file

@ -0,0 +1,97 @@
# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
#
# When uploading crates to the registry Cargo will automatically
# "normalize" Cargo.toml files for maximal compatibility
# with all versions of Cargo and also rewrite `path` dependencies
# to registry (e.g., crates.io) dependencies.
#
# If you are reading this file be aware that the original Cargo.toml
# will likely look very different (and much more reasonable).
# See Cargo.toml.orig for the original contents.
[package]
edition = "2021"
name = "swc_ecma_ast"
version = "0.109.0"
authors = ["강동윤 <kdy1997.dev@gmail.com>"]
description = "Ecmascript ast."
documentation = "https://rustdoc.swc.rs/swc_ecma_ast/"
license = "Apache-2.0"
repository = "https://github.com/swc-project/swc.git"
[package.metadata.docs.rs]
all-features = true
rustdoc-args = [
"--cfg",
"docsrs",
]
[lib]
bench = false
[dependencies.arbitrary]
version = "1"
features = ["derive"]
optional = true
[dependencies.bitflags]
version = "2.3.2"
[dependencies.bytecheck]
version = "0.6.10"
optional = true
[dependencies.is-macro]
version = "0.3.0"
[dependencies.num-bigint]
version = "0.4"
features = ["serde"]
[dependencies.rkyv]
version = "=0.7.42"
features = [
"strict",
"validation",
]
optional = true
package = "rkyv"
[dependencies.scoped-tls]
version = "1.0.1"
[dependencies.serde]
version = "1.0.133"
features = ["derive"]
optional = true
[dependencies.string_enum]
version = "0.4.1"
[dependencies.swc_atoms]
version = "0.5.9"
[dependencies.swc_common]
version = "0.32.0"
[dependencies.unicode-id]
version = "0.3"
[dev-dependencies.serde_json]
version = "1"
[features]
__rkyv = []
default = []
fuzzing = [
"arbitrary",
"swc_common/arbitrary",
]
rkyv-impl = [
"__rkyv",
"rkyv",
"bytecheck",
"swc_atoms/rkyv-impl",
"swc_common/rkyv-impl",
]
serde-impl = ["serde"]

View file

@ -0,0 +1,348 @@
use is_macro::Is;
use swc_common::{ast_node, util::take::Take, EqIgnoreSpan, Span, DUMMY_SP};
use crate::{
expr::Expr,
function::{Function, ParamOrTsParamProp},
ident::PrivateName,
prop::PropName,
stmt::BlockStmt,
typescript::{
Accessibility, TsExprWithTypeArgs, TsIndexSignature, TsTypeAnn, TsTypeParamDecl,
TsTypeParamInstantiation,
},
BigInt, ComputedPropName, EmptyStmt, Id, Ident, Number,
};
#[ast_node]
#[derive(Eq, Hash, EqIgnoreSpan)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
pub struct Class {
pub span: Span,
#[cfg_attr(c, serde(default))]
pub decorators: Vec<Decorator>,
#[cfg_attr(feature = "serde-impl", serde(default))]
pub body: Vec<ClassMember>,
#[cfg_attr(feature = "serde-impl", serde(default))]
pub super_class: Option<Box<Expr>>,
#[cfg_attr(feature = "serde-impl", serde(default))]
pub is_abstract: bool,
#[cfg_attr(feature = "serde-impl", serde(default))]
pub type_params: Option<Box<TsTypeParamDecl>>,
#[cfg_attr(feature = "serde-impl", serde(default))]
pub super_type_params: Option<Box<TsTypeParamInstantiation>>,
/// Typescript extension.
#[cfg_attr(feature = "serde-impl", serde(default))]
pub implements: Vec<TsExprWithTypeArgs>,
}
impl Take for Class {
fn dummy() -> Self {
Class {
span: DUMMY_SP,
decorators: Default::default(),
body: Default::default(),
super_class: Default::default(),
is_abstract: Default::default(),
type_params: Default::default(),
super_type_params: Default::default(),
implements: Default::default(),
}
}
}
#[ast_node]
#[derive(Eq, Hash, Is, EqIgnoreSpan)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
pub enum ClassMember {
#[tag("Constructor")]
Constructor(Constructor),
/// `es2015`
#[tag("ClassMethod")]
Method(ClassMethod),
#[tag("PrivateMethod")]
PrivateMethod(PrivateMethod),
/// stage 0 / Typescript
#[tag("ClassProperty")]
ClassProp(ClassProp),
#[tag("PrivateProperty")]
PrivateProp(PrivateProp),
#[tag("TsIndexSignature")]
TsIndexSignature(TsIndexSignature),
#[tag("EmptyStatement")]
Empty(EmptyStmt),
/// Stage 3
#[tag("StaticBlock")]
StaticBlock(StaticBlock),
/// Stage 3
#[tag("AutoAccessor")]
AutoAccessor(AutoAccessor),
}
impl Take for ClassMember {
fn dummy() -> Self {
ClassMember::Empty(EmptyStmt { span: DUMMY_SP })
}
}
#[ast_node("ClassProperty")]
#[derive(Eq, Hash, EqIgnoreSpan)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
pub struct ClassProp {
#[cfg_attr(feature = "serde-impl", serde(default))]
pub span: Span,
pub key: PropName,
#[cfg_attr(feature = "serde-impl", serde(default))]
pub value: Option<Box<Expr>>,
#[cfg_attr(feature = "serde-impl", serde(default, rename = "typeAnnotation"))]
pub type_ann: Option<Box<TsTypeAnn>>,
#[cfg_attr(feature = "serde-impl", serde(default))]
pub is_static: bool,
#[cfg_attr(feature = "serde-impl", serde(default))]
pub decorators: Vec<Decorator>,
/// Typescript extension.
#[cfg_attr(feature = "serde-impl", serde(default))]
pub accessibility: Option<Accessibility>,
/// Typescript extension.
#[cfg_attr(feature = "serde-impl", serde(default))]
pub is_abstract: bool,
#[cfg_attr(feature = "serde-impl", serde(default))]
pub is_optional: bool,
#[cfg_attr(feature = "serde-impl", serde(default))]
pub is_override: bool,
#[cfg_attr(feature = "serde-impl", serde(default))]
pub readonly: bool,
#[cfg_attr(feature = "serde-impl", serde(default))]
pub declare: bool,
#[cfg_attr(feature = "serde-impl", serde(default))]
pub definite: bool,
}
#[ast_node("PrivateProperty")]
#[derive(Eq, Hash, EqIgnoreSpan)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
pub struct PrivateProp {
#[cfg_attr(feature = "serde-impl", serde(default))]
pub span: Span,
pub key: PrivateName,
#[cfg_attr(feature = "serde-impl", serde(default))]
pub value: Option<Box<Expr>>,
#[cfg_attr(feature = "serde-impl", serde(default, rename = "typeAnnotation"))]
pub type_ann: Option<Box<TsTypeAnn>>,
#[cfg_attr(feature = "serde-impl", serde(default))]
pub is_static: bool,
#[cfg_attr(feature = "serde-impl", serde(default))]
pub decorators: Vec<Decorator>,
/// Typescript extension.
#[cfg_attr(feature = "serde-impl", serde(default))]
pub accessibility: Option<Accessibility>,
#[cfg_attr(feature = "serde-impl", serde(default))]
pub is_optional: bool,
#[cfg_attr(feature = "serde-impl", serde(default))]
pub is_override: bool,
#[cfg_attr(feature = "serde-impl", serde(default))]
pub readonly: bool,
#[cfg_attr(feature = "serde-impl", serde(default))]
pub definite: bool,
}
macro_rules! method {
($name:ident, $ty:literal, $KEY:ty) => {
#[ast_node($ty)]
#[derive(Eq, Hash, EqIgnoreSpan)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
pub struct $name {
#[cfg_attr(feature = "serde-impl", serde(default))]
pub span: Span,
pub key: $KEY,
pub function: Box<Function>,
pub kind: MethodKind,
#[cfg_attr(feature = "serde-impl", serde(default))]
pub is_static: bool,
/// Typescript extension.
#[cfg_attr(feature = "serde-impl", serde(default))]
pub accessibility: Option<Accessibility>,
/// Typescript extension.
#[cfg_attr(feature = "serde-impl", serde(default))]
pub is_abstract: bool,
#[cfg_attr(feature = "serde-impl", serde(default))]
pub is_optional: bool,
#[cfg_attr(feature = "serde-impl", serde(default))]
pub is_override: bool,
}
};
}
method!(ClassMethod, "ClassMethod", PropName);
method!(PrivateMethod, "PrivateMethod", PrivateName);
#[ast_node("Constructor")]
#[derive(Eq, Hash, EqIgnoreSpan)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
pub struct Constructor {
pub span: Span,
pub key: PropName,
pub params: Vec<ParamOrTsParamProp>,
#[cfg_attr(feature = "serde-impl", serde(default))]
pub body: Option<BlockStmt>,
#[cfg_attr(feature = "serde-impl", serde(default))]
pub accessibility: Option<Accessibility>,
#[cfg_attr(feature = "serde-impl", serde(default))]
pub is_optional: bool,
}
#[ast_node("Decorator")]
#[derive(Eq, Hash, EqIgnoreSpan)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
pub struct Decorator {
pub span: Span,
#[cfg_attr(feature = "serde-impl", serde(rename = "expression"))]
pub expr: Box<Expr>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, EqIgnoreSpan)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[cfg_attr(
any(feature = "rkyv-impl"),
derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)
)]
#[cfg_attr(feature = "rkyv-impl", archive(check_bytes))]
#[cfg_attr(feature = "rkyv-impl", archive_attr(repr(u32)))]
#[cfg_attr(feature = "serde-impl", derive(serde::Serialize, serde::Deserialize))]
pub enum MethodKind {
#[cfg_attr(feature = "serde-impl", serde(rename = "method"))]
Method,
#[cfg_attr(feature = "serde-impl", serde(rename = "getter"))]
Getter,
#[cfg_attr(feature = "serde-impl", serde(rename = "setter"))]
Setter,
}
#[ast_node("StaticBlock")]
#[derive(Eq, Hash, EqIgnoreSpan)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
pub struct StaticBlock {
pub span: Span,
pub body: BlockStmt,
}
impl Take for StaticBlock {
fn dummy() -> Self {
StaticBlock {
span: DUMMY_SP,
body: Take::dummy(),
}
}
}
/// Either a private name or a public name.
#[ast_node]
#[derive(Is, Eq, Hash, EqIgnoreSpan)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
pub enum Key {
#[tag("PrivateName")]
Private(PrivateName),
#[tag("Identifier")]
#[tag("StringLiteral")]
#[tag("NumericLiteral")]
#[tag("Computed")]
#[tag("BigIntLiteral")]
Public(PropName),
}
bridge_from!(Key, PropName, Ident);
bridge_from!(Key, PropName, Id);
bridge_from!(Key, PropName, Number);
bridge_from!(Key, PropName, ComputedPropName);
bridge_from!(Key, PropName, BigInt);
impl Take for Key {
fn dummy() -> Self {
Key::Public(Take::dummy())
}
}
#[ast_node("AutoAccessor")]
#[derive(Eq, Hash, EqIgnoreSpan)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
pub struct AutoAccessor {
#[cfg_attr(feature = "serde-impl", serde(default))]
pub span: Span,
pub key: Key,
#[cfg_attr(feature = "serde-impl", serde(default))]
pub value: Option<Box<Expr>>,
#[cfg_attr(feature = "serde-impl", serde(default, rename = "typeAnnotation"))]
pub type_ann: Option<Box<TsTypeAnn>>,
#[cfg_attr(feature = "serde-impl", serde(default))]
pub is_static: bool,
#[cfg_attr(feature = "serde-impl", serde(default))]
pub decorators: Vec<Decorator>,
/// Typescript extension.
#[cfg_attr(feature = "serde-impl", serde(default))]
pub accessibility: Option<Accessibility>,
}
impl Take for AutoAccessor {
fn dummy() -> AutoAccessor {
AutoAccessor {
span: Take::dummy(),
key: Take::dummy(),
value: Take::dummy(),
type_ann: None,
is_static: false,
decorators: Take::dummy(),
accessibility: None,
}
}
}

View file

@ -0,0 +1,196 @@
use is_macro::Is;
use string_enum::StringEnum;
use swc_common::{ast_node, util::take::Take, EqIgnoreSpan, Span, DUMMY_SP};
use crate::{
class::Class,
expr::Expr,
function::Function,
ident::Ident,
pat::Pat,
typescript::{TsEnumDecl, TsInterfaceDecl, TsModuleDecl, TsTypeAliasDecl},
};
#[ast_node]
#[derive(Eq, Hash, Is, EqIgnoreSpan)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
pub enum Decl {
#[tag("ClassDeclaration")]
Class(ClassDecl),
#[tag("FunctionDeclaration")]
#[is(name = "fn_decl")]
Fn(FnDecl),
#[tag("VariableDeclaration")]
Var(Box<VarDecl>),
#[tag("UsingDeclaration")]
Using(Box<UsingDecl>),
#[tag("TsInterfaceDeclaration")]
TsInterface(Box<TsInterfaceDecl>),
#[tag("TsTypeAliasDeclaration")]
TsTypeAlias(Box<TsTypeAliasDecl>),
#[tag("TsEnumDeclaration")]
TsEnum(Box<TsEnumDecl>),
#[tag("TsModuleDeclaration")]
TsModule(Box<TsModuleDecl>),
}
bridge_decl_from!(Box<VarDecl>, VarDecl);
bridge_decl_from!(Box<UsingDecl>, UsingDecl);
bridge_decl_from!(Box<TsInterfaceDecl>, TsInterfaceDecl);
bridge_decl_from!(Box<TsTypeAliasDecl>, TsTypeAliasDecl);
bridge_decl_from!(Box<TsEnumDecl>, TsEnumDecl);
bridge_decl_from!(Box<TsModuleDecl>, TsModuleDecl);
bridge_stmt_from!(Decl, ClassDecl);
bridge_stmt_from!(Decl, FnDecl);
impl Take for Decl {
fn dummy() -> Self {
Decl::Var(Take::dummy())
}
}
#[ast_node("FunctionDeclaration")]
#[derive(Eq, Hash, EqIgnoreSpan)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
pub struct FnDecl {
#[cfg_attr(feature = "serde-impl", serde(rename = "identifier"))]
pub ident: Ident,
#[cfg_attr(feature = "serde-impl", serde(default))]
pub declare: bool,
#[cfg_attr(feature = "serde-impl", serde(flatten))]
#[span]
pub function: Box<Function>,
}
impl Take for FnDecl {
fn dummy() -> Self {
FnDecl {
ident: Take::dummy(),
declare: Default::default(),
function: Take::dummy(),
}
}
}
#[ast_node("ClassDeclaration")]
#[derive(Eq, Hash, EqIgnoreSpan)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
pub struct ClassDecl {
#[cfg_attr(feature = "serde-impl", serde(rename = "identifier"))]
pub ident: Ident,
#[cfg_attr(feature = "serde-impl", serde(default))]
pub declare: bool,
#[cfg_attr(feature = "serde-impl", serde(flatten))]
#[span]
pub class: Box<Class>,
}
impl Take for ClassDecl {
fn dummy() -> Self {
ClassDecl {
ident: Take::dummy(),
declare: Default::default(),
class: Take::dummy(),
}
}
}
#[ast_node("VariableDeclaration")]
#[derive(Eq, Hash, EqIgnoreSpan)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
pub struct VarDecl {
pub span: Span,
pub kind: VarDeclKind,
#[cfg_attr(feature = "serde-impl", serde(default))]
pub declare: bool,
#[cfg_attr(feature = "serde-impl", serde(rename = "declarations"))]
pub decls: Vec<VarDeclarator>,
}
impl Take for VarDecl {
fn dummy() -> Self {
VarDecl {
span: DUMMY_SP,
kind: VarDeclKind::Var,
declare: Default::default(),
decls: Take::dummy(),
}
}
}
#[derive(StringEnum, Clone, Copy, Eq, PartialEq, PartialOrd, Ord, Hash, EqIgnoreSpan)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[cfg_attr(
any(feature = "rkyv-impl"),
derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)
)]
#[cfg_attr(feature = "rkyv-impl", archive(check_bytes))]
#[cfg_attr(feature = "rkyv-impl", archive_attr(repr(u32)))]
pub enum VarDeclKind {
/// `var`
Var,
/// `let`
Let,
/// `const`
Const,
}
#[ast_node("VariableDeclarator")]
#[derive(Eq, Hash, EqIgnoreSpan)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
pub struct VarDeclarator {
pub span: Span,
#[cfg_attr(feature = "serde-impl", serde(rename = "id"))]
pub name: Pat,
/// Initialization expression.
#[cfg_attr(feature = "serde-impl", serde(default))]
pub init: Option<Box<Expr>>,
/// Typescript only
#[cfg_attr(feature = "serde-impl", serde(default))]
pub definite: bool,
}
impl Take for VarDeclarator {
fn dummy() -> Self {
VarDeclarator {
span: DUMMY_SP,
name: Take::dummy(),
init: Take::dummy(),
definite: Default::default(),
}
}
}
#[ast_node("UsingDeclaration")]
#[derive(Eq, Hash, EqIgnoreSpan)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
pub struct UsingDecl {
#[cfg_attr(feature = "serde-impl", serde(default))]
pub span: Span,
#[cfg_attr(feature = "serde-impl", serde(default))]
pub is_await: bool,
#[cfg_attr(feature = "serde-impl", serde(default))]
pub decls: Vec<VarDeclarator>,
}
impl Take for UsingDecl {
fn dummy() -> Self {
Self {
span: DUMMY_SP,
is_await: Default::default(),
decls: Take::dummy(),
}
}
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,84 @@
use is_macro::Is;
use swc_common::{ast_node, util::take::Take, EqIgnoreSpan, Span, DUMMY_SP};
use crate::{
class::Decorator,
pat::Pat,
stmt::BlockStmt,
typescript::{TsParamProp, TsTypeAnn, TsTypeParamDecl},
};
/// Common parts of function and method.
#[ast_node]
#[derive(Eq, Hash, EqIgnoreSpan)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
pub struct Function {
pub params: Vec<Param>,
#[cfg_attr(feature = "serde-impl", serde(default))]
pub decorators: Vec<Decorator>,
pub span: Span,
#[cfg_attr(feature = "serde-impl", serde(default))]
pub body: Option<BlockStmt>,
/// if it's a generator.
#[cfg_attr(feature = "serde-impl", serde(default, rename = "generator"))]
pub is_generator: bool,
/// if it's an async function.
#[cfg_attr(feature = "serde-impl", serde(default, rename = "async"))]
pub is_async: bool,
#[cfg_attr(feature = "serde-impl", serde(default, rename = "typeParameters"))]
pub type_params: Option<Box<TsTypeParamDecl>>,
#[cfg_attr(feature = "serde-impl", serde(default))]
pub return_type: Option<Box<TsTypeAnn>>,
}
impl Take for Function {
fn dummy() -> Self {
Function {
params: Take::dummy(),
decorators: Take::dummy(),
span: DUMMY_SP,
body: Take::dummy(),
is_generator: false,
is_async: false,
type_params: Take::dummy(),
return_type: Take::dummy(),
}
}
}
#[ast_node("Parameter")]
#[derive(Eq, Hash, EqIgnoreSpan)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
pub struct Param {
pub span: Span,
#[cfg_attr(feature = "serde-impl", serde(default))]
pub decorators: Vec<Decorator>,
pub pat: Pat,
}
impl From<Pat> for Param {
fn from(pat: Pat) -> Self {
Self {
span: DUMMY_SP,
decorators: Default::default(),
pat,
}
}
}
#[ast_node]
#[derive(Eq, Hash, Is, EqIgnoreSpan)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
pub enum ParamOrTsParamProp {
#[tag("TsParameterProperty")]
TsParamProp(TsParamProp),
#[tag("Parameter")]
Param(Param),
}

View file

@ -0,0 +1,413 @@
use std::fmt::Display;
use scoped_tls::scoped_thread_local;
use swc_atoms::{js_word, JsWord};
use swc_common::{
ast_node, util::take::Take, BytePos, EqIgnoreSpan, Span, Spanned, SyntaxContext, DUMMY_SP,
};
use unicode_id::UnicodeID;
use crate::typescript::TsTypeAnn;
/// Identifier used as a pattern.
#[derive(Spanned, Clone, Debug, PartialEq, Eq, Hash, EqIgnoreSpan)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[cfg_attr(
any(feature = "rkyv-impl"),
derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)
)]
#[cfg_attr(
any(feature = "rkyv-impl"),
archive(bound(
serialize = "__S: rkyv::ser::Serializer + rkyv::ser::ScratchSpace + \
rkyv::ser::SharedSerializeRegistry",
deserialize = "__D: rkyv::de::SharedDeserializeRegistry"
))
)]
#[cfg_attr(feature = "rkyv-impl", archive(check_bytes))]
#[cfg_attr(feature = "rkyv-impl", archive_attr(repr(C)))]
#[cfg_attr(feature = "serde-impl", derive(serde::Serialize, serde::Deserialize))]
pub struct BindingIdent {
#[span]
#[cfg_attr(feature = "serde-impl", serde(flatten))]
#[cfg_attr(feature = "__rkyv", omit_bounds)]
pub id: Ident,
#[cfg_attr(feature = "serde-impl", serde(default, rename = "typeAnnotation"))]
#[cfg_attr(feature = "__rkyv", omit_bounds)]
pub type_ann: Option<Box<TsTypeAnn>>,
}
impl std::ops::Deref for BindingIdent {
type Target = Ident;
fn deref(&self) -> &Self::Target {
&self.id
}
}
impl BindingIdent {
/// See [`Ident::to_id`] for documentation.
pub fn to_id(&self) -> Id {
self.id.to_id()
}
}
impl From<Ident> for BindingIdent {
fn from(id: Ident) -> Self {
Self { id, type_ann: None }
}
}
bridge_from!(BindingIdent, Ident, Id);
/// A complete identifier with span.
///
/// Identifier of swc consists of two parts. The first one is symbol, which is
/// stored using an interned string, [JsWord] . The second
/// one is [SyntaxContext][swc_common::SyntaxContext], which can be
/// used to distinguish identifier with same symbol.
///
/// Let me explain this with an example.
///
/// ```ts
/// let a = 5
/// {
/// let a = 3;
/// }
/// ```
/// In the code above, there are two variables with the symbol a.
///
///
/// Other compilers typically uses type like `Scope`, and store them nested, but
/// in rust, type like `Scope` requires [Arc<Mutex<Scope>>] so swc uses
/// different approach. Instead of passing scopes, swc annotates two variables
/// with different tag, which is named
/// [SyntaxContext]. The notation for the syntax
/// context is #n where n is a number. e.g. `foo#1`
///
/// For the example above, after applying resolver pass, it becomes.
///
/// ```ts
/// let a#1 = 5
/// {
/// let a#2 = 3;
/// }
/// ```
///
/// Thanks to the `tag` we attached, we can now distinguish them.
///
/// ([JsWord], [SyntaxContext])
///
/// See [Id], which is a type alias for this.
///
/// This can be used to store all variables in a module to single hash map.
///
/// # Comparison
///
/// While comparing two identifiers, you can use `.to_id()`.
///
/// # HashMap
///
/// There's a type named [Id] which only contains minimal information to
/// distinguish identifiers.
#[ast_node("Identifier")]
#[derive(Eq, Hash)]
pub struct Ident {
pub span: Span,
#[cfg_attr(feature = "serde-impl", serde(rename = "value"))]
#[cfg_attr(any(feature = "rkyv-impl"), with(swc_atoms::EncodeJsWord))]
pub sym: JsWord,
/// TypeScript only. Used in case of an optional parameter.
#[cfg_attr(feature = "serde-impl", serde(default))]
pub optional: bool,
}
scoped_thread_local!(static EQ_IGNORE_SPAN_IGNORE_CTXT: ());
impl EqIgnoreSpan for Ident {
fn eq_ignore_span(&self, other: &Self) -> bool {
if self.sym != other.sym {
return false;
}
if self.span.ctxt == other.span.ctxt {
return true;
}
EQ_IGNORE_SPAN_IGNORE_CTXT.is_set()
}
}
impl From<Id> for Ident {
fn from(id: Id) -> Self {
Ident::new(id.0, DUMMY_SP.with_ctxt(id.1))
}
}
impl From<Ident> for Id {
fn from(i: Ident) -> Self {
(i.sym, i.span.ctxt)
}
}
impl Ident {
/// In `op`, [EqIgnoreSpan] of [Ident] will ignore the syntax context.
pub fn within_ignored_ctxt<F, Ret>(op: F) -> Ret
where
F: FnOnce() -> Ret,
{
EQ_IGNORE_SPAN_IGNORE_CTXT.set(&(), op)
}
/// Preserve syntax context while drop `span.lo` and `span.hi`.
pub fn without_loc(mut self) -> Ident {
self.span.lo = BytePos::DUMMY;
self.span.hi = BytePos::DUMMY;
self
}
/// Creates `Id` using `JsWord` and `SyntaxContext` of `self`.
pub fn to_id(&self) -> Id {
(self.sym.clone(), self.span.ctxt)
}
/// Returns true if `c` is a valid character for an identifier start.
#[inline]
pub fn is_valid_start(c: char) -> bool {
c == '$' || c == '_' || c.is_ascii_alphabetic() || {
if c.is_ascii() {
false
} else {
UnicodeID::is_id_start(c)
}
}
}
/// Returns true if `c` is a valid character for an identifier part after
/// start.
#[inline]
pub fn is_valid_continue(c: char) -> bool {
c == '$' || c == '_' || c == '\u{200c}' || c == '\u{200d}' || c.is_ascii_alphanumeric() || {
if c.is_ascii() {
false
} else {
UnicodeID::is_id_continue(c)
}
}
}
/// Alternative for `toIdentifier` of babel.
///
/// Returns [Ok] if it's a valid identifier and [Err] if it's not valid.
/// The returned [Err] contains the valid symbol.
pub fn verify_symbol(s: &str) -> Result<(), String> {
fn is_reserved_symbol(s: &str) -> bool {
s.is_reserved() || s.is_reserved_in_strict_mode(true) || s.is_reserved_in_strict_bind()
}
if is_reserved_symbol(s) {
let mut buf = String::with_capacity(s.len() + 1);
buf.push('_');
buf.push_str(s);
return Err(buf);
}
{
let mut chars = s.chars();
if let Some(first) = chars.next() {
if Self::is_valid_start(first) && chars.all(Self::is_valid_continue) {
return Ok(());
}
}
}
let mut buf = String::with_capacity(s.len() + 2);
let mut has_start = false;
for c in s.chars() {
if !has_start && Self::is_valid_start(c) {
has_start = true;
buf.push(c);
continue;
}
if Self::is_valid_continue(c) {
buf.push(c);
}
}
if buf.is_empty() {
buf.push('_');
}
if is_reserved_symbol(&buf) {
let mut new_buf = String::with_capacity(buf.len() + 1);
new_buf.push('_');
new_buf.push_str(&buf);
buf = new_buf;
}
Err(buf)
}
#[inline]
pub fn is_dummy(&self) -> bool {
self.sym == js_word!("") && self.span.is_dummy()
}
}
/// See [Ident] for documentation.
pub type Id = (JsWord, SyntaxContext);
impl Take for Ident {
fn dummy() -> Self {
Ident::new(js_word!(""), DUMMY_SP)
}
}
impl Display for Ident {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}{:?}", self.sym, self.span.ctxt)
}
}
#[cfg(feature = "arbitrary")]
#[cfg_attr(docsrs, doc(cfg(feature = "arbitrary")))]
impl<'a> arbitrary::Arbitrary<'a> for Ident {
fn arbitrary(u: &mut arbitrary::Unstructured<'_>) -> arbitrary::Result<Self> {
let span = u.arbitrary()?;
let sym = u.arbitrary::<String>()?;
if sym.is_empty() {
return Err(arbitrary::Error::NotEnoughData);
}
let sym = sym.into();
let optional = u.arbitrary()?;
Ok(Self {
span,
sym,
optional,
})
}
}
#[ast_node("PrivateName")]
#[derive(Eq, Hash, EqIgnoreSpan)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
pub struct PrivateName {
pub span: Span,
pub id: Ident,
}
impl AsRef<str> for Ident {
fn as_ref(&self) -> &str {
&self.sym
}
}
impl Ident {
pub const fn new(sym: JsWord, span: Span) -> Self {
Ident {
span,
sym,
optional: false,
}
}
}
pub trait IdentExt: AsRef<str> {
fn is_reserved(&self) -> bool {
[
"break",
"case",
"catch",
"class",
"const",
"continue",
"debugger",
"default",
"delete",
"do",
"else",
"enum",
"export",
"extends",
"false",
"finally",
"for",
"function",
"if",
"import",
"in",
"instanceof",
"new",
"null",
"package",
"return",
"super",
"switch",
"this",
"throw",
"true",
"try",
"typeof",
"var",
"void",
"while",
"with",
]
.contains(&self.as_ref())
}
fn is_reserved_in_strict_mode(&self, is_module: bool) -> bool {
if is_module && self.as_ref() == "await" {
return true;
}
[
"implements",
"interface",
"let",
"package",
"private",
"protected",
"public",
"static",
"yield",
]
.contains(&self.as_ref())
}
fn is_reserved_in_strict_bind(&self) -> bool {
["eval", "arguments"].contains(&self.as_ref())
}
fn is_reserved_in_es3(&self) -> bool {
[
"abstract",
"boolean",
"byte",
"char",
"double",
"final",
"float",
"goto",
"int",
"long",
"native",
"short",
"synchronized",
"throws",
"transient",
"volatile",
]
.contains(&self.as_ref())
}
}
impl IdentExt for JsWord {}
impl IdentExt for Ident {}
impl IdentExt for &'_ str {}
impl IdentExt for String {}

View file

@ -0,0 +1,306 @@
use is_macro::Is;
use swc_atoms::Atom;
use swc_common::{ast_node, util::take::Take, EqIgnoreSpan, Span, DUMMY_SP};
use crate::{
expr::{Expr, SpreadElement},
ident::Ident,
lit::Lit,
typescript::TsTypeParamInstantiation,
};
/// Used for `obj` property of `JSXMemberExpr`.
#[ast_node]
#[derive(Eq, Hash, Is, EqIgnoreSpan)]
#[allow(variant_size_differences)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
pub enum JSXObject {
#[tag("JSXMemberExpression")]
JSXMemberExpr(Box<JSXMemberExpr>),
#[tag("Identifier")]
Ident(Ident),
}
#[ast_node("JSXMemberExpression")]
#[derive(Eq, Hash, EqIgnoreSpan)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
pub struct JSXMemberExpr {
#[cfg_attr(feature = "serde-impl", serde(rename = "object"))]
#[span(lo)]
pub obj: JSXObject,
#[cfg_attr(feature = "serde-impl", serde(rename = "property"))]
#[span(hi)]
pub prop: Ident,
}
/// XML-based namespace syntax:
#[ast_node("JSXNamespacedName")]
#[derive(Eq, Hash, EqIgnoreSpan)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
pub struct JSXNamespacedName {
#[cfg_attr(feature = "serde-impl", serde(rename = "namespace"))]
#[span(lo)]
pub ns: Ident,
#[span(hi)]
pub name: Ident,
}
#[ast_node("JSXEmptyExpression")]
#[derive(Eq, Hash, Copy, EqIgnoreSpan)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
pub struct JSXEmptyExpr {
pub span: Span,
}
#[ast_node("JSXExpressionContainer")]
#[derive(Eq, Hash, EqIgnoreSpan)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
pub struct JSXExprContainer {
pub span: Span,
#[cfg_attr(feature = "serde-impl", serde(rename = "expression"))]
pub expr: JSXExpr,
}
#[ast_node]
#[derive(Eq, Hash, EqIgnoreSpan)]
#[allow(variant_size_differences)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
pub enum JSXExpr {
#[tag("JSXEmptyExpression")]
JSXEmptyExpr(JSXEmptyExpr),
#[tag("*")]
Expr(Box<Expr>),
}
#[ast_node("JSXSpreadChild")]
#[derive(Eq, Hash, EqIgnoreSpan)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
pub struct JSXSpreadChild {
pub span: Span,
#[cfg_attr(feature = "serde-impl", serde(rename = "expression"))]
pub expr: Box<Expr>,
}
#[ast_node]
#[derive(Eq, Hash, EqIgnoreSpan)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
pub enum JSXElementName {
#[tag("Identifier")]
Ident(Ident),
#[tag("JSXMemberExpression")]
JSXMemberExpr(JSXMemberExpr),
#[tag("JSXNamespacedName")]
JSXNamespacedName(JSXNamespacedName),
}
impl Take for JSXElementName {
fn dummy() -> Self {
JSXElementName::Ident(Take::dummy())
}
}
#[ast_node("JSXOpeningElement")]
#[derive(Eq, Hash, EqIgnoreSpan)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
pub struct JSXOpeningElement {
pub name: JSXElementName,
pub span: Span,
#[cfg_attr(feature = "serde-impl", serde(default, rename = "attributes"))]
pub attrs: Vec<JSXAttrOrSpread>,
#[cfg_attr(feature = "serde-impl", serde(rename = "selfClosing"))]
pub self_closing: bool,
/// Note: This field's name is different from one from babel because it is
/// misleading
#[cfg_attr(feature = "serde-impl", serde(default, rename = "typeArguments"))]
pub type_args: Option<Box<TsTypeParamInstantiation>>,
}
impl Take for JSXOpeningElement {
fn dummy() -> Self {
JSXOpeningElement {
name: Take::dummy(),
span: DUMMY_SP,
attrs: Take::dummy(),
self_closing: Default::default(),
type_args: Take::dummy(),
}
}
}
#[ast_node]
#[derive(Eq, Hash, EqIgnoreSpan)]
#[allow(variant_size_differences)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
pub enum JSXAttrOrSpread {
#[tag("JSXAttribute")]
JSXAttr(JSXAttr),
#[tag("SpreadElement")]
SpreadElement(SpreadElement),
}
#[ast_node("JSXClosingElement")]
#[derive(Eq, Hash, EqIgnoreSpan)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
pub struct JSXClosingElement {
pub span: Span,
pub name: JSXElementName,
}
#[ast_node("JSXAttribute")]
#[derive(Eq, Hash, EqIgnoreSpan)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
pub struct JSXAttr {
pub span: Span,
pub name: JSXAttrName,
/// Babel uses Expr instead of JSXAttrValue
pub value: Option<JSXAttrValue>,
}
#[ast_node]
#[derive(Eq, Hash, EqIgnoreSpan)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
pub enum JSXAttrName {
#[tag("Identifier")]
Ident(Ident),
#[tag("JSXNamespacedName")]
JSXNamespacedName(JSXNamespacedName),
}
#[ast_node]
#[derive(Eq, Hash, EqIgnoreSpan)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
pub enum JSXAttrValue {
#[tag("StringLiteral")]
#[tag("BooleanLiteral")]
#[tag("NullLiteral")]
#[tag("NumericLiteral")]
#[tag("RegExpLiteral")]
#[tag("JSXText")]
Lit(Lit),
#[tag("JSXExpressionContainer")]
JSXExprContainer(JSXExprContainer),
#[tag("JSXElement")]
JSXElement(Box<JSXElement>),
#[tag("JSXFragment")]
JSXFragment(JSXFragment),
}
#[ast_node("JSXText")]
#[derive(Eq, Hash, EqIgnoreSpan)]
pub struct JSXText {
pub span: Span,
pub value: Atom,
pub raw: Atom,
}
#[cfg(feature = "arbitrary")]
#[cfg_attr(docsrs, doc(cfg(feature = "arbitrary")))]
impl<'a> arbitrary::Arbitrary<'a> for JSXText {
fn arbitrary(u: &mut arbitrary::Unstructured<'_>) -> arbitrary::Result<Self> {
let span = u.arbitrary()?;
let value = u.arbitrary::<String>()?.into();
let raw = u.arbitrary::<String>()?.into();
Ok(Self { span, value, raw })
}
}
#[ast_node("JSXElement")]
#[derive(Eq, Hash, EqIgnoreSpan)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
pub struct JSXElement {
pub span: Span,
pub opening: JSXOpeningElement,
pub children: Vec<JSXElementChild>,
pub closing: Option<JSXClosingElement>,
}
impl Take for JSXElement {
fn dummy() -> Self {
JSXElement {
span: DUMMY_SP,
opening: Take::dummy(),
children: Take::dummy(),
closing: Take::dummy(),
}
}
}
#[ast_node]
#[derive(Eq, Hash, EqIgnoreSpan)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
pub enum JSXElementChild {
#[tag("JSXText")]
JSXText(JSXText),
#[tag("JSXExpressionContainer")]
JSXExprContainer(JSXExprContainer),
#[tag("JSXSpreadChild")]
JSXSpreadChild(JSXSpreadChild),
#[tag("JSXElement")]
JSXElement(Box<JSXElement>),
#[tag("JSXFragment")]
JSXFragment(JSXFragment),
}
#[ast_node("JSXFragment")]
#[derive(Eq, Hash, EqIgnoreSpan)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
pub struct JSXFragment {
pub span: Span,
pub opening: JSXOpeningFragment,
#[cfg_attr(feature = "serde-impl", serde(default))]
pub children: Vec<JSXElementChild>,
pub closing: JSXClosingFragment,
}
impl Take for JSXFragment {
fn dummy() -> Self {
JSXFragment {
span: DUMMY_SP,
opening: Take::dummy(),
children: Take::dummy(),
closing: Take::dummy(),
}
}
}
#[ast_node("JSXOpeningFragment")]
#[derive(Eq, Hash, Copy, EqIgnoreSpan)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
pub struct JSXOpeningFragment {
pub span: Span,
}
impl Take for JSXOpeningFragment {
fn dummy() -> Self {
JSXOpeningFragment { span: DUMMY_SP }
}
}
#[ast_node("JSXClosingFragment")]
#[derive(Eq, Hash, Copy, EqIgnoreSpan)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
pub struct JSXClosingFragment {
pub span: Span,
}
impl Take for JSXClosingFragment {
fn dummy() -> Self {
JSXClosingFragment { span: DUMMY_SP }
}
}

View file

@ -0,0 +1,244 @@
#![cfg_attr(docsrs, feature(doc_cfg))]
#![deny(unreachable_patterns)]
#![deny(missing_copy_implementations)]
#![deny(trivial_casts)]
#![deny(trivial_numeric_casts)]
#![deny(unreachable_pub)]
#![deny(clippy::all)]
#![allow(clippy::enum_variant_names)]
#![allow(clippy::clone_on_copy)]
#![recursion_limit = "1024"]
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
use swc_common::{ast_node, EqIgnoreSpan, Span};
pub use self::{
class::{
AutoAccessor, Class, ClassMember, ClassMethod, ClassProp, Constructor, Decorator, Key,
MethodKind, PrivateMethod, PrivateProp, StaticBlock,
},
decl::{ClassDecl, Decl, FnDecl, UsingDecl, VarDecl, VarDeclKind, VarDeclarator},
expr::{
ArrayLit, ArrowExpr, AssignExpr, AwaitExpr, BinExpr, BlockStmtOrExpr, CallExpr, Callee,
ClassExpr, CondExpr, Expr, ExprOrSpread, FnExpr, Import, MemberExpr, MemberProp,
MetaPropExpr, MetaPropKind, NewExpr, ObjectLit, OptCall, OptChainBase, OptChainExpr,
ParenExpr, PatOrExpr, PropOrSpread, SeqExpr, SpreadElement, Super, SuperProp,
SuperPropExpr, TaggedTpl, ThisExpr, Tpl, TplElement, UnaryExpr, UpdateExpr, YieldExpr,
},
function::{Function, Param, ParamOrTsParamProp},
ident::{BindingIdent, Id, Ident, IdentExt, PrivateName},
jsx::{
JSXAttr, JSXAttrName, JSXAttrOrSpread, JSXAttrValue, JSXClosingElement, JSXClosingFragment,
JSXElement, JSXElementChild, JSXElementName, JSXEmptyExpr, JSXExpr, JSXExprContainer,
JSXFragment, JSXMemberExpr, JSXNamespacedName, JSXObject, JSXOpeningElement,
JSXOpeningFragment, JSXSpreadChild, JSXText,
},
list::ListFormat,
lit::{BigInt, Bool, Lit, Null, Number, Regex, Str},
module::{Module, ModuleItem, Program, ReservedUnused, Script},
module_decl::{
DefaultDecl, ExportAll, ExportDecl, ExportDefaultDecl, ExportDefaultExpr,
ExportDefaultSpecifier, ExportNamedSpecifier, ExportNamespaceSpecifier, ExportSpecifier,
ImportDecl, ImportDefaultSpecifier, ImportNamedSpecifier, ImportSpecifier,
ImportStarAsSpecifier, ModuleDecl, ModuleExportName, NamedExport,
},
operators::{AssignOp, BinaryOp, UnaryOp, UpdateOp},
pat::{
ArrayPat, AssignPat, AssignPatProp, KeyValuePatProp, ObjectPat, ObjectPatProp, Pat, RestPat,
},
prop::{
AssignProp, ComputedPropName, GetterProp, KeyValueProp, MethodProp, Prop, PropName,
SetterProp,
},
source_map::{SourceMapperExt, SpanExt},
stmt::{
BlockStmt, BreakStmt, CatchClause, ContinueStmt, DebuggerStmt, DoWhileStmt, EmptyStmt,
ExprStmt, ForHead, ForInStmt, ForOfStmt, ForStmt, IfStmt, LabeledStmt, ReturnStmt, Stmt,
SwitchCase, SwitchStmt, ThrowStmt, TryStmt, VarDeclOrExpr, WhileStmt, WithStmt,
},
typescript::{
Accessibility, TruePlusMinus, TsArrayType, TsAsExpr, TsCallSignatureDecl,
TsConditionalType, TsConstAssertion, TsConstructSignatureDecl, TsConstructorType,
TsEntityName, TsEnumDecl, TsEnumMember, TsEnumMemberId, TsExportAssignment,
TsExprWithTypeArgs, TsExternalModuleRef, TsFnOrConstructorType, TsFnParam, TsFnType,
TsGetterSignature, TsImportEqualsDecl, TsImportType, TsIndexSignature, TsIndexedAccessType,
TsInferType, TsInstantiation, TsInterfaceBody, TsInterfaceDecl, TsIntersectionType,
TsKeywordType, TsKeywordTypeKind, TsLit, TsLitType, TsMappedType, TsMethodSignature,
TsModuleBlock, TsModuleDecl, TsModuleName, TsModuleRef, TsNamespaceBody, TsNamespaceDecl,
TsNamespaceExportDecl, TsNonNullExpr, TsOptionalType, TsParamProp, TsParamPropParam,
TsParenthesizedType, TsPropertySignature, TsQualifiedName, TsRestType, TsSatisfiesExpr,
TsSetterSignature, TsThisType, TsThisTypeOrIdent, TsTplLitType, TsTupleElement,
TsTupleType, TsType, TsTypeAliasDecl, TsTypeAnn, TsTypeAssertion, TsTypeElement, TsTypeLit,
TsTypeOperator, TsTypeOperatorOp, TsTypeParam, TsTypeParamDecl, TsTypeParamInstantiation,
TsTypePredicate, TsTypeQuery, TsTypeQueryExpr, TsTypeRef, TsUnionOrIntersectionType,
TsUnionType,
},
};
#[macro_use]
mod macros;
mod class;
mod decl;
mod expr;
mod function;
mod ident;
mod jsx;
mod list;
mod lit;
mod module;
mod module_decl;
mod operators;
mod pat;
mod prop;
mod source_map;
mod stmt;
mod typescript;
/// Represents a invalid node.
#[ast_node("Invalid")]
#[derive(Eq, Hash, Copy, EqIgnoreSpan)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
pub struct Invalid {
pub span: Span,
}
/// Note: This type implements `Serailize` and `Deserialize` if `serde` is
/// enabled, instead of requiring `serde-impl` feature.
#[derive(Debug, Clone, Copy, PartialOrd, Ord, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum EsVersion {
#[cfg_attr(feature = "serde", serde(rename = "es3"))]
Es3,
#[cfg_attr(feature = "serde", serde(rename = "es5"))]
Es5,
#[cfg_attr(feature = "serde", serde(rename = "es2015"))]
Es2015,
#[cfg_attr(feature = "serde", serde(rename = "es2016"))]
Es2016,
#[cfg_attr(feature = "serde", serde(rename = "es2017"))]
Es2017,
#[cfg_attr(feature = "serde", serde(rename = "es2018"))]
Es2018,
#[cfg_attr(feature = "serde", serde(rename = "es2019"))]
Es2019,
#[cfg_attr(feature = "serde", serde(rename = "es2020"))]
Es2020,
#[cfg_attr(feature = "serde", serde(rename = "es2021"))]
Es2021,
#[cfg_attr(feature = "serde", serde(rename = "es2022"))]
Es2022,
#[cfg_attr(feature = "serde", serde(rename = "esnext"))]
EsNext,
}
impl EsVersion {
/// Get the latest version. This is `es2022` for now, but it will be changed
/// if a new version of specification is released.
pub const fn latest() -> Self {
EsVersion::Es2022
}
}
impl Default for EsVersion {
fn default() -> Self {
EsVersion::Es5
}
}
/// Warning: The particular implementation of serialization and deserialization
/// of the ast nodes may change in the future, and so these types would be
/// removed. It's safe to say they will be serializable in some form or another,
/// but not necessarily with these specific types underlying the implementation.
/// As such, *use these types at your own risk*.
#[cfg(feature = "rkyv-impl")]
#[doc(hidden)]
pub use self::{
class::{
ArchivedAutoAccessor, ArchivedClass, ArchivedClassMember, ArchivedClassMethod,
ArchivedClassProp, ArchivedConstructor, ArchivedDecorator, ArchivedKey, ArchivedMethodKind,
ArchivedPrivateMethod, ArchivedPrivateProp, ArchivedStaticBlock,
},
decl::{
ArchivedClassDecl, ArchivedDecl, ArchivedFnDecl, ArchivedUsingDecl, ArchivedVarDecl,
ArchivedVarDeclKind, ArchivedVarDeclarator,
},
expr::{
ArchivedArrayLit, ArchivedArrowExpr, ArchivedAssignExpr, ArchivedAwaitExpr,
ArchivedBinExpr, ArchivedBlockStmtOrExpr, ArchivedCallExpr, ArchivedCallee,
ArchivedClassExpr, ArchivedCondExpr, ArchivedExpr, ArchivedExprOrSpread, ArchivedFnExpr,
ArchivedImport, ArchivedMemberExpr, ArchivedMemberProp, ArchivedMetaPropExpr,
ArchivedMetaPropKind, ArchivedNewExpr, ArchivedObjectLit, ArchivedOptCall,
ArchivedOptChainBase, ArchivedOptChainExpr, ArchivedParenExpr, ArchivedPatOrExpr,
ArchivedPropOrSpread, ArchivedSeqExpr, ArchivedSpreadElement, ArchivedSuper,
ArchivedSuperProp, ArchivedSuperPropExpr, ArchivedTaggedTpl, ArchivedThisExpr, ArchivedTpl,
ArchivedTplElement, ArchivedUnaryExpr, ArchivedUpdateExpr, ArchivedYieldExpr,
},
function::{ArchivedFunction, ArchivedParam, ArchivedParamOrTsParamProp},
ident::{ArchivedBindingIdent, ArchivedIdent, ArchivedPrivateName},
jsx::{
ArchivedJSXAttr, ArchivedJSXAttrName, ArchivedJSXAttrOrSpread, ArchivedJSXAttrValue,
ArchivedJSXClosingElement, ArchivedJSXClosingFragment, ArchivedJSXElement,
ArchivedJSXElementChild, ArchivedJSXElementName, ArchivedJSXEmptyExpr, ArchivedJSXExpr,
ArchivedJSXExprContainer, ArchivedJSXFragment, ArchivedJSXMemberExpr,
ArchivedJSXNamespacedName, ArchivedJSXObject, ArchivedJSXOpeningElement,
ArchivedJSXOpeningFragment, ArchivedJSXSpreadChild, ArchivedJSXText,
},
lit::{
ArchivedBigInt, ArchivedBool, ArchivedLit, ArchivedNull, ArchivedNumber, ArchivedRegex,
ArchivedStr,
},
module::{
ArchivedModule, ArchivedModuleItem, ArchivedProgram, ArchivedReservedUnused, ArchivedScript,
},
module_decl::{
ArchivedDefaultDecl, ArchivedExportAll, ArchivedExportDecl, ArchivedExportDefaultDecl,
ArchivedExportDefaultExpr, ArchivedExportDefaultSpecifier, ArchivedExportNamedSpecifier,
ArchivedExportNamespaceSpecifier, ArchivedExportSpecifier, ArchivedImportDecl,
ArchivedImportDefaultSpecifier, ArchivedImportNamedSpecifier, ArchivedImportSpecifier,
ArchivedImportStarAsSpecifier, ArchivedModuleDecl, ArchivedModuleExportName,
ArchivedNamedExport,
},
operators::{ArchivedAssignOp, ArchivedBinaryOp, ArchivedUnaryOp, ArchivedUpdateOp},
pat::{
ArchivedArrayPat, ArchivedAssignPat, ArchivedAssignPatProp, ArchivedKeyValuePatProp,
ArchivedObjectPat, ArchivedObjectPatProp, ArchivedPat, ArchivedRestPat,
},
prop::{
ArchivedAssignProp, ArchivedComputedPropName, ArchivedGetterProp, ArchivedKeyValueProp,
ArchivedMethodProp, ArchivedProp, ArchivedPropName, ArchivedSetterProp,
},
stmt::{
ArchivedBlockStmt, ArchivedBreakStmt, ArchivedCatchClause, ArchivedContinueStmt,
ArchivedDebuggerStmt, ArchivedDoWhileStmt, ArchivedEmptyStmt, ArchivedExprStmt,
ArchivedForHead, ArchivedForInStmt, ArchivedForOfStmt, ArchivedForStmt, ArchivedIfStmt,
ArchivedLabeledStmt, ArchivedReturnStmt, ArchivedStmt, ArchivedSwitchCase,
ArchivedSwitchStmt, ArchivedThrowStmt, ArchivedTryStmt, ArchivedVarDeclOrExpr,
ArchivedWhileStmt, ArchivedWithStmt,
},
typescript::{
ArchivedAccessibility, ArchivedTruePlusMinus, ArchivedTsArrayType, ArchivedTsAsExpr,
ArchivedTsCallSignatureDecl, ArchivedTsConditionalType, ArchivedTsConstAssertion,
ArchivedTsConstructSignatureDecl, ArchivedTsConstructorType, ArchivedTsEntityName,
ArchivedTsEnumDecl, ArchivedTsEnumMember, ArchivedTsEnumMemberId,
ArchivedTsExportAssignment, ArchivedTsExprWithTypeArgs, ArchivedTsExternalModuleRef,
ArchivedTsFnOrConstructorType, ArchivedTsFnParam, ArchivedTsFnType,
ArchivedTsGetterSignature, ArchivedTsImportEqualsDecl, ArchivedTsImportType,
ArchivedTsIndexSignature, ArchivedTsIndexedAccessType, ArchivedTsInferType,
ArchivedTsInstantiation, ArchivedTsInterfaceBody, ArchivedTsInterfaceDecl,
ArchivedTsIntersectionType, ArchivedTsKeywordType, ArchivedTsKeywordTypeKind,
ArchivedTsLit, ArchivedTsLitType, ArchivedTsMappedType, ArchivedTsMethodSignature,
ArchivedTsModuleBlock, ArchivedTsModuleDecl, ArchivedTsModuleName, ArchivedTsModuleRef,
ArchivedTsNamespaceBody, ArchivedTsNamespaceDecl, ArchivedTsNamespaceExportDecl,
ArchivedTsNonNullExpr, ArchivedTsOptionalType, ArchivedTsParamProp,
ArchivedTsParamPropParam, ArchivedTsParenthesizedType, ArchivedTsPropertySignature,
ArchivedTsQualifiedName, ArchivedTsRestType, ArchivedTsSatisfiesExpr,
ArchivedTsSetterSignature, ArchivedTsThisType, ArchivedTsThisTypeOrIdent,
ArchivedTsTplLitType, ArchivedTsTupleElement, ArchivedTsTupleType, ArchivedTsType,
ArchivedTsTypeAliasDecl, ArchivedTsTypeAnn, ArchivedTsTypeAssertion, ArchivedTsTypeElement,
ArchivedTsTypeLit, ArchivedTsTypeOperator, ArchivedTsTypeOperatorOp, ArchivedTsTypeParam,
ArchivedTsTypeParamDecl, ArchivedTsTypeParamInstantiation, ArchivedTsTypePredicate,
ArchivedTsTypeQuery, ArchivedTsTypeQueryExpr, ArchivedTsTypeRef,
ArchivedTsUnionOrIntersectionType, ArchivedTsUnionType,
},
};

View file

@ -0,0 +1,211 @@
#![allow(unused)]
#![allow(non_upper_case_globals)]
use bitflags::bitflags;
bitflags! {
/// Represents the formatting rule for a list of nodes.
#[derive(PartialEq, Eq, Copy, Clone)]
pub struct ListFormat: u32 {
/// Default value.
const None = 0;
// Line separators
/// Prints the list on a single line (default).
const SingleLine = 0;
/// Prints the list on multiple lines.
const MultiLine = 1 << 0;
/// Prints the list using line preservation if possible.
const PreserveLines = 1 << 1;
const LinesMask = Self::MultiLine.bits() | Self::PreserveLines.bits();
// Delimiters
/// There is no delimiter between list items (default).
const NotDelimited = 0;
/// Each list item is space-and-bar (" |") delimited.
const BarDelimited = 1 << 2;
/// Each list item is space-and-ampersand (" &") delimited.
const AmpersandDelimited = 1 << 3;
/// Each list item is comma (";") delimited.
const CommaDelimited = 1 << 4;
const DelimitersMask = Self::BarDelimited.bits()
| Self::AmpersandDelimited.bits()
| Self::CommaDelimited.bits();
// Write a trailing comma (";") if present.
const AllowTrailingComma = 1 << 5;
// Whitespace
/// The list should be indented.
const Indented = 1 << 6;
/// Inserts a space after the opening brace and before the closing
/// brace.
const SpaceBetweenBraces = 1 << 7;
/// Inserts a space between each sibling node.
const SpaceBetweenSiblings = 1 << 8;
// Brackets/Braces
/// The list is surrounded by "{" and "}".
const Braces = 1 << 9;
/// The list is surrounded by "(" and ")".
const Parenthesis = 1 << 10;
/// The list is surrounded by "<" and ">".
const AngleBrackets = 1 << 11;
/// The list is surrounded by "[" and "]".
const SquareBrackets = 1 << 12;
const BracketsMask = Self::Braces.bits()
| Self::Parenthesis.bits()
| Self::AngleBrackets.bits()
| Self::SquareBrackets.bits();
/// Do not emit brackets if the list is undefined.
const OptionalIfUndefined = 1 << 13;
/// Do not emit brackets if the list is empty.
const OptionalIfEmpty = 1 << 14;
const Optional = Self::OptionalIfUndefined.bits() | Self::OptionalIfEmpty.bits();
// Others
/// Prefer adding a LineTerminator between synthesized nodes.
const PreferNewLine = 1 << 15;
/// Do not emit a trailing NewLine for a MultiLine list.
const NoTrailingNewLine = 1 << 16;
/// Do not emit comments between each node
const NoInterveningComments = 1 << 17;
/// If the literal is empty; do not add spaces between braces.
const NoSpaceIfEmpty = 1 << 18;
const SingleElement = 1 << 19;
const ForceTrailingComma = 1 << 20;
// Optimization.
const CanSkipTrailingComma = 1 << 21;
// Precomputed Formats
const Modifiers = Self::SingleLine.bits()
| Self::SpaceBetweenSiblings.bits()
| Self::NoInterveningComments.bits();
const HeritageClauses = Self::SingleLine.bits() | Self::SpaceBetweenSiblings.bits();
const SingleLineTypeLiteralMembers = Self::SingleLine.bits()
| Self::SpaceBetweenBraces.bits()
| Self::SpaceBetweenSiblings.bits()
| Self::Indented.bits();
const MultiLineTypeLiteralMembers = Self::MultiLine.bits() | Self::Indented.bits();
const TupleTypeElements = Self::CommaDelimited.bits()
| Self::SpaceBetweenSiblings.bits()
| Self::SingleLine.bits()
| Self::Indented.bits();
const UnionTypeConstituents = Self::BarDelimited.bits()
| Self::SpaceBetweenSiblings.bits()
| Self::SingleLine.bits();
const IntersectionTypeConstituents = Self::AmpersandDelimited.bits()
| Self::SpaceBetweenSiblings.bits()
| Self::SingleLine.bits();
const ObjectBindingPatternElements = Self::SingleLine.bits()
| Self::SpaceBetweenBraces.bits()
| Self::CommaDelimited.bits()
| Self::SpaceBetweenSiblings.bits()
| Self::NoSpaceIfEmpty.bits();
const ArrayBindingPatternElements = Self::SingleLine.bits()
| Self::CommaDelimited.bits()
| Self::SpaceBetweenSiblings.bits()
| Self::NoSpaceIfEmpty.bits();
const ObjectLiteralExpressionProperties = Self::MultiLine.bits()
| Self::CommaDelimited.bits()
| Self::SpaceBetweenSiblings.bits()
| Self::SpaceBetweenBraces.bits()
| Self::Indented.bits()
| Self::Braces.bits()
| Self::NoSpaceIfEmpty.bits();
const ArrayLiteralExpressionElements = Self::PreserveLines.bits()
| Self::CommaDelimited.bits()
| Self::SpaceBetweenSiblings.bits()
| Self::Indented.bits()
| Self::SquareBrackets.bits();
const CommaListElements = Self::CommaDelimited.bits()
| Self::SpaceBetweenSiblings.bits()
| Self::SingleLine.bits();
const CallExpressionArguments = Self::CommaDelimited.bits()
| Self::SpaceBetweenSiblings.bits()
| Self::SingleLine.bits()
| Self::Parenthesis.bits();
const NewExpressionArguments = Self::CommaDelimited.bits()
| Self::SpaceBetweenSiblings.bits()
| Self::SingleLine.bits()
| Self::Parenthesis.bits()
| Self::OptionalIfUndefined.bits();
const TemplateExpressionSpans = Self::SingleLine.bits() | Self::NoInterveningComments.bits();
const SingleLineBlockStatements = Self::SpaceBetweenBraces.bits()
| Self::SpaceBetweenSiblings.bits()
| Self::SingleLine.bits();
const MultiLineBlockStatements = Self::Indented.bits() | Self::MultiLine.bits();
const VariableDeclarationList = Self::CommaDelimited.bits()
| Self::SpaceBetweenSiblings.bits()
| Self::SingleLine.bits();
const SingleLineFunctionBodyStatements = Self::SingleLine.bits()
| Self::SpaceBetweenSiblings.bits()
| Self::SpaceBetweenBraces.bits();
const MultiLineFunctionBodyStatements = Self::MultiLine.bits();
const ClassHeritageClauses = Self::SingleLine.bits() | Self::SpaceBetweenSiblings.bits();
const ClassMembers = Self::Indented.bits() | Self::MultiLine.bits();
const InterfaceMembers = Self::Indented.bits() | Self::MultiLine.bits();
const EnumMembers = Self::CommaDelimited.bits() | Self::Indented.bits() | Self::MultiLine.bits();
const CaseBlockClauses = Self::Indented.bits() | Self::MultiLine.bits();
const NamedImportsOrExportsElements = Self::CommaDelimited.bits()
| Self::SpaceBetweenSiblings.bits()
| Self::AllowTrailingComma.bits()
| Self::SingleLine.bits()
| Self::SpaceBetweenBraces.bits();
const JsxElementOrFragmentChildren = Self::SingleLine.bits() | Self::NoInterveningComments.bits();
const JsxElementAttributes = Self::SingleLine.bits()
| Self::SpaceBetweenSiblings.bits()
| Self::NoInterveningComments.bits();
const CaseOrDefaultClauseStatements = Self::Indented.bits()
| Self::MultiLine.bits()
| Self::NoTrailingNewLine.bits()
| Self::OptionalIfEmpty.bits();
const HeritageClauseTypes = Self::CommaDelimited.bits()
| Self::SpaceBetweenSiblings.bits()
| Self::SingleLine.bits();
const SourceFileStatements = Self::MultiLine.bits() | Self::NoTrailingNewLine.bits();
const Decorators = Self::MultiLine.bits() | Self::Optional.bits();
const TypeArguments = Self::CommaDelimited.bits()
| Self::SpaceBetweenSiblings.bits()
| Self::SingleLine.bits()
| Self::AngleBrackets.bits()
| Self::Optional.bits();
const TypeParameters = Self::CommaDelimited.bits()
| Self::SpaceBetweenSiblings.bits()
| Self::SingleLine.bits()
| Self::AngleBrackets.bits()
| Self::Optional.bits();
const Parameters = Self::CommaDelimited.bits()
| Self::SpaceBetweenSiblings.bits()
| Self::SingleLine.bits()
| Self::Parenthesis.bits();
const IndexSignatureParameters = Self::CommaDelimited.bits()
| Self::SpaceBetweenSiblings.bits()
| Self::SingleLine.bits()
| Self::Indented.bits()
| Self::SquareBrackets.bits();
}
}
impl ListFormat {
pub fn opening_bracket(self) -> &'static str {
match self & ListFormat::BracketsMask {
ListFormat::Braces => "{",
ListFormat::Parenthesis => "(",
ListFormat::AngleBrackets => "<",
ListFormat::SquareBrackets => "[",
_ => unreachable!(),
}
}
pub fn closing_bracket(self) -> &'static str {
match self & ListFormat::BracketsMask {
ListFormat::Braces => "}",
ListFormat::Parenthesis => ")",
ListFormat::AngleBrackets => ">",
ListFormat::SquareBrackets => "]",
_ => unreachable!(),
}
}
}

View file

@ -0,0 +1,420 @@
use std::{
borrow::Cow,
fmt::{self, Display, Formatter},
hash::{Hash, Hasher},
};
use num_bigint::BigInt as BigIntValue;
use swc_atoms::{js_word, Atom, JsWord};
use swc_common::{ast_node, util::take::Take, EqIgnoreSpan, Span, DUMMY_SP};
use crate::jsx::JSXText;
#[ast_node]
#[derive(Eq, Hash, EqIgnoreSpan)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
pub enum Lit {
#[tag("StringLiteral")]
Str(Str),
#[tag("BooleanLiteral")]
Bool(Bool),
#[tag("NullLiteral")]
Null(Null),
#[tag("NumericLiteral")]
Num(Number),
#[tag("BigIntLiteral")]
BigInt(BigInt),
#[tag("RegExpLiteral")]
Regex(Regex),
#[tag("JSXText")]
JSXText(JSXText),
}
macro_rules! bridge_lit_from {
($bridge: ty, $src:ty) => {
bridge_expr_from!(crate::Lit, $src);
bridge_from!(Lit, $bridge, $src);
};
}
bridge_expr_from!(Lit, Str);
bridge_expr_from!(Lit, Bool);
bridge_expr_from!(Lit, Number);
bridge_expr_from!(Lit, BigInt);
bridge_expr_from!(Lit, Regex);
bridge_expr_from!(Lit, Null);
bridge_expr_from!(Lit, JSXText);
bridge_lit_from!(Str, &'_ str);
bridge_lit_from!(Str, JsWord);
bridge_lit_from!(Str, Atom);
bridge_lit_from!(Str, Cow<'_, str>);
bridge_lit_from!(Str, String);
bridge_lit_from!(Bool, bool);
bridge_lit_from!(Number, f64);
bridge_lit_from!(Number, usize);
bridge_lit_from!(BigInt, BigIntValue);
#[ast_node("BigIntLiteral")]
#[derive(Eq, Hash)]
pub struct BigInt {
pub span: Span,
#[cfg_attr(any(feature = "rkyv-impl"), with(EncodeBigInt))]
pub value: Box<BigIntValue>,
/// Use `None` value only for transformations to avoid recalculate
/// characters in big integer
pub raw: Option<Atom>,
}
impl EqIgnoreSpan for BigInt {
fn eq_ignore_span(&self, other: &Self) -> bool {
self.value == other.value
}
}
#[cfg(feature = "rkyv-impl")]
#[derive(Debug, Clone, Copy)]
#[cfg_attr(feature = "rkyv-impl", derive(rkyv::bytecheck::CheckBytes))]
#[cfg_attr(feature = "rkyv-impl", repr(C))]
pub struct EncodeBigInt;
#[cfg(feature = "rkyv-impl")]
impl rkyv::with::ArchiveWith<Box<BigIntValue>> for EncodeBigInt {
type Archived = rkyv::Archived<String>;
type Resolver = rkyv::Resolver<String>;
unsafe fn resolve_with(
field: &Box<BigIntValue>,
pos: usize,
resolver: Self::Resolver,
out: *mut Self::Archived,
) {
use rkyv::Archive;
let s = field.to_string();
s.resolve(pos, resolver, out);
}
}
#[cfg(feature = "rkyv-impl")]
impl<S> rkyv::with::SerializeWith<Box<BigIntValue>, S> for EncodeBigInt
where
S: ?Sized + rkyv::ser::Serializer,
{
fn serialize_with(
field: &Box<BigIntValue>,
serializer: &mut S,
) -> Result<Self::Resolver, S::Error> {
let field = field.to_string();
rkyv::string::ArchivedString::serialize_from_str(&field, serializer)
}
}
#[cfg(feature = "rkyv-impl")]
impl<D> rkyv::with::DeserializeWith<rkyv::Archived<String>, Box<BigIntValue>, D> for EncodeBigInt
where
D: ?Sized + rkyv::Fallible,
{
fn deserialize_with(
field: &rkyv::Archived<String>,
deserializer: &mut D,
) -> Result<Box<BigIntValue>, D::Error> {
use rkyv::Deserialize;
let s: String = field.deserialize(deserializer)?;
Ok(Box::new(s.parse().unwrap()))
}
}
#[cfg(feature = "arbitrary")]
#[cfg_attr(docsrs, doc(cfg(feature = "arbitrary")))]
impl<'a> arbitrary::Arbitrary<'a> for BigInt {
fn arbitrary(u: &mut arbitrary::Unstructured<'_>) -> arbitrary::Result<Self> {
let span = u.arbitrary()?;
let value = Box::new(u.arbitrary::<usize>()?.into());
let raw = Some(u.arbitrary::<String>()?.into());
Ok(Self { span, value, raw })
}
}
impl From<BigIntValue> for BigInt {
#[inline]
fn from(value: BigIntValue) -> Self {
BigInt {
span: DUMMY_SP,
value: Box::new(value),
raw: None,
}
}
}
/// A string literal.
#[ast_node("StringLiteral")]
#[derive(Eq, Hash)]
pub struct Str {
pub span: Span,
#[cfg_attr(any(feature = "rkyv-impl"), with(swc_atoms::EncodeJsWord))]
pub value: JsWord,
/// Use `None` value only for transformations to avoid recalculate escaped
/// characters in strings
pub raw: Option<Atom>,
}
impl Take for Str {
fn dummy() -> Self {
Str {
span: DUMMY_SP,
value: js_word!(""),
raw: None,
}
}
}
#[cfg(feature = "arbitrary")]
#[cfg_attr(docsrs, doc(cfg(feature = "arbitrary")))]
impl<'a> arbitrary::Arbitrary<'a> for Str {
fn arbitrary(u: &mut arbitrary::Unstructured<'_>) -> arbitrary::Result<Self> {
let span = u.arbitrary()?;
let value = u.arbitrary::<String>()?.into();
let raw = Some(u.arbitrary::<String>()?.into());
Ok(Self { span, value, raw })
}
}
impl Str {
#[inline]
pub fn is_empty(&self) -> bool {
self.value.is_empty()
}
}
impl EqIgnoreSpan for Str {
fn eq_ignore_span(&self, other: &Self) -> bool {
self.value == other.value
}
}
impl From<JsWord> for Str {
#[inline]
fn from(value: JsWord) -> Self {
Str {
span: DUMMY_SP,
value,
raw: None,
}
}
}
impl From<Atom> for Str {
#[inline]
fn from(value: Atom) -> Self {
Str {
span: DUMMY_SP,
value: JsWord::from(&*value),
raw: None,
}
}
}
bridge_from!(Str, JsWord, &'_ str);
bridge_from!(Str, JsWord, String);
bridge_from!(Str, JsWord, Cow<'_, str>);
/// A boolean literal.
///
///
/// # Creation
///
/// If you are creating a boolean literal with a dummy span, please use
/// `true.into()` or `false.into()`, instead of creating this struct directly.
///
/// All of `Box<Expr>`, `Expr`, `Lit`, `Bool` implements `From<bool>`.
#[ast_node("BooleanLiteral")]
#[derive(Copy, Eq, Hash, EqIgnoreSpan)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
pub struct Bool {
pub span: Span,
pub value: bool,
}
impl Take for Bool {
fn dummy() -> Self {
Bool {
span: DUMMY_SP,
value: false,
}
}
}
impl From<bool> for Bool {
#[inline]
fn from(value: bool) -> Self {
Bool {
span: DUMMY_SP,
value,
}
}
}
#[ast_node("NullLiteral")]
#[derive(Copy, Eq, Hash, EqIgnoreSpan)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
pub struct Null {
pub span: Span,
}
impl Take for Null {
fn dummy() -> Self {
Null { span: DUMMY_SP }
}
}
#[ast_node("RegExpLiteral")]
#[derive(Eq, Hash, EqIgnoreSpan)]
pub struct Regex {
pub span: Span,
#[cfg_attr(feature = "serde-impl", serde(rename = "pattern"))]
pub exp: Atom,
#[cfg_attr(feature = "serde-impl", serde(default))]
pub flags: Atom,
}
impl Take for Regex {
fn dummy() -> Self {
Self {
span: DUMMY_SP,
exp: Default::default(),
flags: Default::default(),
}
}
}
#[cfg(feature = "arbitrary")]
#[cfg_attr(docsrs, doc(cfg(feature = "arbitrary")))]
impl<'a> arbitrary::Arbitrary<'a> for Regex {
fn arbitrary(u: &mut arbitrary::Unstructured<'_>) -> arbitrary::Result<Self> {
let span = u.arbitrary()?;
let exp = u.arbitrary::<String>()?.into();
let flags = "".into(); // TODO
Ok(Self { span, exp, flags })
}
}
/// A numeric literal.
///
///
/// # Creation
///
/// If you are creating a numeric literal with a dummy span, please use
/// `literal.into()`, instead of creating this struct directly.
///
/// All of `Box<Expr>`, `Expr`, `Lit`, `Number` implements `From<64>` and
/// `From<usize>`.
#[ast_node("NumericLiteral")]
pub struct Number {
pub span: Span,
/// **Note**: This should not be `NaN`. Use [crate::Ident] to represent NaN.
///
/// If you store `NaN` in this field, a hash map will behave strangely.
pub value: f64,
/// Use `None` value only for transformations to avoid recalculate
/// characters in number literal
pub raw: Option<Atom>,
}
impl Eq for Number {}
impl EqIgnoreSpan for Number {
fn eq_ignore_span(&self, other: &Self) -> bool {
self.value == other.value && self.value.is_sign_positive() == other.value.is_sign_positive()
}
}
#[allow(clippy::derived_hash_with_manual_eq)]
#[allow(clippy::transmute_float_to_int)]
impl Hash for Number {
fn hash<H: Hasher>(&self, state: &mut H) {
fn integer_decode(val: f64) -> (u64, i16, i8) {
let bits: u64 = val.to_bits();
let sign: i8 = if bits >> 63 == 0 { 1 } else { -1 };
let mut exponent: i16 = ((bits >> 52) & 0x7ff) as i16;
let mantissa = if exponent == 0 {
(bits & 0xfffffffffffff) << 1
} else {
(bits & 0xfffffffffffff) | 0x10000000000000
};
exponent -= 1023 + 52;
(mantissa, exponent, sign)
}
self.span.hash(state);
integer_decode(self.value).hash(state);
self.raw.hash(state);
}
}
impl Display for Number {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
if self.value.is_infinite() {
if self.value.is_sign_positive() {
Display::fmt("Infinity", f)
} else {
Display::fmt("-Infinity", f)
}
} else {
Display::fmt(&self.value, f)
}
}
}
#[cfg(feature = "arbitrary")]
#[cfg_attr(docsrs, doc(cfg(feature = "arbitrary")))]
impl<'a> arbitrary::Arbitrary<'a> for Number {
fn arbitrary(u: &mut arbitrary::Unstructured<'_>) -> arbitrary::Result<Self> {
let span = u.arbitrary()?;
let value = u.arbitrary::<f64>()?;
let raw = Some(u.arbitrary::<String>()?.into());
Ok(Self { span, value, raw })
}
}
impl From<f64> for Number {
#[inline]
fn from(value: f64) -> Self {
Number {
span: DUMMY_SP,
value,
raw: None,
}
}
}
impl From<usize> for Number {
#[inline]
fn from(value: usize) -> Self {
Number {
span: DUMMY_SP,
value: value as _,
raw: None,
}
}
}

View file

@ -0,0 +1,237 @@
/// Creates a corresponding operator. This macro is used to make code more
/// readable.
///
/// This can used to represent [UnaryOp](crate::UnaryOp),
/// [BinaryOp](crate::BinaryOp), or [AssignOp](crate::AssignOp).
///
/// Actual type is determined by the input.
///
/// # Note about `+` and `-`
///
/// As this macro is intended to be used in anywhere, including pattern
/// bindings, this macro cannot use trick to determine type for `+` and `-`.
///
/// So we have to use some special syntax for `+` and `-`:
///
/// - If you need [UnaryOp](crate::UnaryOp), use `op!(unary, "+")` and
/// `op!(unary, "-")`.
///
/// - If you need [BinaryOp](crate::BinaryOp), use `op!(bin, "+")` and
/// `op!(bin, "-")`.
#[macro_export]
macro_rules! op {
(unary,"-") => {
$crate::UnaryOp::Minus
};
(unary,"+") => {
$crate::UnaryOp::Plus
};
("!") => {
$crate::UnaryOp::Bang
};
("~") => {
$crate::UnaryOp::Tilde
};
("typeof") => {
$crate::UnaryOp::TypeOf
};
("void") => {
$crate::UnaryOp::Void
};
("delete") => {
$crate::UnaryOp::Delete
};
("++") => {
$crate::UpdateOp::PlusPlus
};
("--") => {
$crate::UpdateOp::MinusMinus
};
("==") => {
$crate::BinaryOp::EqEq
};
("!=") => {
$crate::BinaryOp::NotEq
};
("===") => {
$crate::BinaryOp::EqEqEq
};
("!==") => {
$crate::BinaryOp::NotEqEq
};
("<") => {
$crate::BinaryOp::Lt
};
("<=") => {
$crate::BinaryOp::LtEq
};
(">") => {
$crate::BinaryOp::Gt
};
(">=") => {
$crate::BinaryOp::GtEq
};
("<<") => {
$crate::BinaryOp::LShift
};
(">>") => {
$crate::BinaryOp::RShift
};
(">>>") => {
$crate::BinaryOp::ZeroFillRShift
};
(bin,"+") => {
$crate::BinaryOp::Add
};
(bin,"-") => {
$crate::BinaryOp::Sub
};
("*") => {
$crate::BinaryOp::Mul
};
("/") => {
$crate::BinaryOp::Div
};
("%") => {
$crate::BinaryOp::Mod
};
("|") => {
$crate::BinaryOp::BitOr
};
("^") => {
$crate::BinaryOp::BitXor
};
("&") => {
$crate::BinaryOp::BitAnd
};
("||") => {
$crate::BinaryOp::LogicalOr
};
("&&") => {
$crate::BinaryOp::LogicalAnd
};
("in") => {
$crate::BinaryOp::In
};
("instanceof") => {
$crate::BinaryOp::InstanceOf
};
("**") => {
$crate::BinaryOp::Exp
};
("??") => {
$crate::BinaryOp::NullishCoalescing
};
("=") => {
$crate::AssignOp::Assign
};
("+=") => {
$crate::AssignOp::AddAssign
};
("-=") => {
$crate::AssignOp::SubAssign
};
("*=") => {
$crate::AssignOp::MulAssign
};
("/=") => {
$crate::AssignOp::DivAssign
};
("%=") => {
$crate::AssignOp::ModAssign
};
("<<=") => {
$crate::AssignOp::LShiftAssign
};
(">>=") => {
$crate::AssignOp::RShiftAssign
};
(">>>=") => {
$crate::AssignOp::ZeroFillRShiftAssign
};
("|=") => {
$crate::AssignOp::BitOrAssign
};
("^=") => {
$crate::AssignOp::BitXorAssign
};
("&=") => {
$crate::AssignOp::BitAndAssign
};
("**=") => {
$crate::AssignOp::ExpAssign
};
("&&=") => {
$crate::AssignOp::AndAssign
};
("||=") => {
$crate::AssignOp::OrAssign
};
("??=") => {
$crate::AssignOp::NullishAssign
};
}
macro_rules! test_de {
($name:ident, $T:path, $s:literal) => {
#[test]
#[cfg(feature = "serde-impl")]
fn $name() {
let _var: $T = ::serde_json::from_str(&$s).expect("failed to parse json");
}
};
}
/// Implement `From<$src>` for `$dst`, by using implementation of `From<$src>`
/// for `$bridge`.
///
/// - `$dst` must implement `From<$bridge>`.
/// - `$bridge` must implement `From<$src>`.
///
///
/// e.g. For `&str` -> `Box<Expr>`, we convert it by `&str` -> `JsWord` -> `Str`
/// -> `Lit` -> `Expr` -> `Box<Expr>`.
macro_rules! bridge_from {
($dst:ty, $bridge:ty, $src:ty) => {
impl From<$src> for $dst {
#[cfg_attr(not(debug_assertions), inline(always))]
fn from(src: $src) -> $dst {
let src: $bridge = src.into();
src.into()
}
}
};
}
macro_rules! bridge_expr_from {
($bridge:ty, $src:ty) => {
bridge_from!(crate::Expr, $bridge, $src);
bridge_from!(Box<crate::Expr>, crate::Expr, $src);
};
}
macro_rules! bridge_pat_from {
($bridge:ty, $src:ty) => {
bridge_from!(crate::Pat, $bridge, $src);
bridge_from!(crate::Param, crate::Pat, $src);
bridge_from!(Box<crate::Pat>, crate::Pat, $src);
};
}
macro_rules! bridge_stmt_from {
($bridge:ty, $src:ty) => {
bridge_from!(crate::Stmt, $bridge, $src);
bridge_from!(crate::ModuleItem, crate::Stmt, $src);
};
}
macro_rules! bridge_decl_from {
($bridge:ty, $src:ty) => {
bridge_from!(crate::Decl, $bridge, $src);
bridge_from!(crate::Stmt, crate::Decl, $src);
bridge_from!(crate::ModuleItem, crate::Stmt, $src);
};
}

View file

@ -0,0 +1,131 @@
use is_macro::Is;
use swc_atoms::Atom;
use swc_common::{ast_node, util::take::Take, EqIgnoreSpan, Span, DUMMY_SP};
use crate::{module_decl::ModuleDecl, stmt::Stmt};
#[ast_node]
#[derive(Eq, Hash, Is, EqIgnoreSpan)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
pub enum Program {
#[tag("Module")]
Module(Module),
#[tag("Script")]
Script(Script),
// Reserved type for the testing purpose only. Prod codes does not utilize
// this at all and user should not try to attempt to use this as well.
// TODO: reenable once experimental_metadata breaking change is merged
// #[tag("ReservedUnused")]
// ReservedUnused(ReservedUnused),
}
#[ast_node("ReservedUnused")]
#[derive(Eq, Hash, EqIgnoreSpan)]
pub struct ReservedUnused {
pub span: Span,
pub body: Option<Vec<ModuleItem>>,
}
#[cfg(feature = "arbitrary")]
#[cfg_attr(docsrs, doc(cfg(feature = "arbitrary")))]
impl<'a> arbitrary::Arbitrary<'a> for ReservedUnused {
fn arbitrary(u: &mut arbitrary::Unstructured<'_>) -> arbitrary::Result<Self> {
let span = u.arbitrary()?;
let body = u.arbitrary()?;
Ok(Self { span, body })
}
}
#[ast_node("Module")]
#[derive(Eq, Hash, EqIgnoreSpan)]
pub struct Module {
pub span: Span,
pub body: Vec<ModuleItem>,
#[cfg_attr(feature = "serde-impl", serde(default, rename = "interpreter"))]
pub shebang: Option<Atom>,
}
#[cfg(feature = "arbitrary")]
#[cfg_attr(docsrs, doc(cfg(feature = "arbitrary")))]
impl<'a> arbitrary::Arbitrary<'a> for Module {
fn arbitrary(u: &mut arbitrary::Unstructured<'_>) -> arbitrary::Result<Self> {
let span = u.arbitrary()?;
let body = u.arbitrary()?;
Ok(Self {
span,
body,
shebang: None,
})
}
}
impl Take for Module {
fn dummy() -> Self {
Module {
span: DUMMY_SP,
body: Take::dummy(),
shebang: Take::dummy(),
}
}
}
#[ast_node("Script")]
#[derive(Eq, Hash, EqIgnoreSpan)]
pub struct Script {
pub span: Span,
pub body: Vec<Stmt>,
#[cfg_attr(feature = "serde-impl", serde(default, rename = "interpreter"))]
pub shebang: Option<Atom>,
}
#[cfg(feature = "arbitrary")]
#[cfg_attr(docsrs, doc(cfg(feature = "arbitrary")))]
impl<'a> arbitrary::Arbitrary<'a> for Script {
fn arbitrary(u: &mut arbitrary::Unstructured<'_>) -> arbitrary::Result<Self> {
let span = u.arbitrary()?;
let body = u.arbitrary()?;
Ok(Self {
span,
body,
shebang: None,
})
}
}
impl Take for Script {
fn dummy() -> Self {
Script {
span: DUMMY_SP,
body: Take::dummy(),
shebang: Take::dummy(),
}
}
}
#[ast_node]
#[derive(Eq, Hash, Is, EqIgnoreSpan)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
pub enum ModuleItem {
#[tag("ImportDeclaration")]
#[tag("ExportDeclaration")]
#[tag("ExportNamedDeclaration")]
#[tag("ExportDefaultDeclaration")]
#[tag("ExportDefaultExpression")]
#[tag("ExportAllDeclaration")]
#[tag("TsImportEqualsDeclaration")]
#[tag("TsExportAssignment")]
#[tag("TsNamespaceExportDeclaration")]
ModuleDecl(ModuleDecl),
#[tag("*")]
Stmt(Stmt),
}
impl Take for ModuleItem {
fn dummy() -> Self {
ModuleItem::Stmt(Take::dummy())
}
}

View file

@ -0,0 +1,292 @@
use is_macro::Is;
use swc_common::{ast_node, util::take::Take, EqIgnoreSpan, Span, DUMMY_SP};
use crate::{
decl::Decl,
expr::{ClassExpr, Expr, FnExpr},
ident::Ident,
lit::Str,
typescript::{TsExportAssignment, TsImportEqualsDecl, TsInterfaceDecl, TsNamespaceExportDecl},
ObjectLit,
};
#[ast_node]
#[derive(Eq, Hash, Is, EqIgnoreSpan)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
pub enum ModuleDecl {
#[tag("ImportDeclaration")]
Import(ImportDecl),
#[tag("ExportDeclaration")]
ExportDecl(ExportDecl),
#[tag("ExportNamedDeclaration")]
ExportNamed(NamedExport),
#[tag("ExportDefaultDeclaration")]
ExportDefaultDecl(ExportDefaultDecl),
#[tag("ExportDefaultExpression")]
ExportDefaultExpr(ExportDefaultExpr),
#[tag("ExportAllDeclaration")]
ExportAll(ExportAll),
#[tag("TsImportEqualsDeclaration")]
TsImportEquals(Box<TsImportEqualsDecl>),
#[tag("TsExportAssignment")]
TsExportAssignment(TsExportAssignment),
#[tag("TsNamespaceExportDeclaration")]
TsNamespaceExport(TsNamespaceExportDecl),
}
impl Take for ModuleDecl {
fn dummy() -> Self {
ModuleDecl::Import(ImportDecl::dummy())
}
}
#[ast_node("ExportDefaultExpression")]
#[derive(Eq, Hash, EqIgnoreSpan)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
pub struct ExportDefaultExpr {
pub span: Span,
#[cfg_attr(feature = "serde-impl", serde(rename = "expression"))]
pub expr: Box<Expr>,
}
#[ast_node("ExportDeclaration")]
#[derive(Eq, Hash, EqIgnoreSpan)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
pub struct ExportDecl {
pub span: Span,
#[cfg_attr(feature = "serde-impl", serde(rename = "declaration"))]
pub decl: Decl,
}
#[ast_node("ImportDeclaration")]
#[derive(Eq, Hash, EqIgnoreSpan)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
pub struct ImportDecl {
pub span: Span,
#[cfg_attr(feature = "serde-impl", serde(default))]
pub specifiers: Vec<ImportSpecifier>,
#[cfg_attr(feature = "serde-impl", serde(rename = "source"))]
pub src: Box<Str>,
#[cfg_attr(feature = "serde-impl", serde(default, rename = "typeOnly"))]
pub type_only: bool,
#[cfg_attr(feature = "serde-impl", serde(default))]
pub with: Option<Box<ObjectLit>>,
}
impl Take for ImportDecl {
fn dummy() -> Self {
ImportDecl {
span: DUMMY_SP,
specifiers: Take::dummy(),
src: Take::dummy(),
type_only: Default::default(),
with: Take::dummy(),
}
}
}
/// `export * from 'mod'`
#[ast_node("ExportAllDeclaration")]
#[derive(Eq, Hash, EqIgnoreSpan)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
pub struct ExportAll {
pub span: Span,
#[cfg_attr(feature = "serde-impl", serde(rename = "source"))]
pub src: Box<Str>,
#[cfg_attr(feature = "serde-impl", serde(rename = "typeOnly"))]
pub type_only: bool,
#[cfg_attr(feature = "serde-impl", serde(default))]
pub with: Option<Box<ObjectLit>>,
}
impl Take for ExportAll {
fn dummy() -> Self {
Self {
span: DUMMY_SP,
src: Take::dummy(),
type_only: Default::default(),
with: Take::dummy(),
}
}
}
/// `export { foo } from 'mod'`
/// `export { foo as bar } from 'mod'`
#[ast_node("ExportNamedDeclaration")]
#[derive(Eq, Hash, EqIgnoreSpan)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
pub struct NamedExport {
pub span: Span,
pub specifiers: Vec<ExportSpecifier>,
#[cfg_attr(feature = "serde-impl", serde(rename = "source"))]
pub src: Option<Box<Str>>,
#[cfg_attr(feature = "serde-impl", serde(rename = "typeOnly"))]
pub type_only: bool,
#[cfg_attr(feature = "serde-impl", serde(default))]
pub with: Option<Box<ObjectLit>>,
}
impl Take for NamedExport {
fn dummy() -> Self {
Self {
span: DUMMY_SP,
specifiers: Take::dummy(),
src: Take::dummy(),
type_only: Default::default(),
with: Take::dummy(),
}
}
}
#[ast_node("ExportDefaultDeclaration")]
#[derive(Eq, Hash, EqIgnoreSpan)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
pub struct ExportDefaultDecl {
pub span: Span,
pub decl: DefaultDecl,
}
#[ast_node]
#[derive(Eq, Hash, Is, EqIgnoreSpan)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
pub enum DefaultDecl {
#[tag("ClassExpression")]
Class(ClassExpr),
#[tag("FunctionExpression")]
#[is(name = "fn_expr")]
Fn(FnExpr),
#[tag("TsInterfaceDeclaration")]
TsInterfaceDecl(Box<TsInterfaceDecl>),
}
#[ast_node]
#[derive(Eq, Hash, Is, EqIgnoreSpan)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
pub enum ImportSpecifier {
#[tag("ImportSpecifier")]
Named(ImportNamedSpecifier),
#[tag("ImportDefaultSpecifier")]
Default(ImportDefaultSpecifier),
#[tag("ImportNamespaceSpecifier")]
Namespace(ImportStarAsSpecifier),
}
/// e.g. `import foo from 'mod.js'`
#[ast_node("ImportDefaultSpecifier")]
#[derive(Eq, Hash, EqIgnoreSpan)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
pub struct ImportDefaultSpecifier {
pub span: Span,
pub local: Ident,
}
/// e.g. `import * as foo from 'mod.js'`.
#[ast_node("ImportNamespaceSpecifier")]
#[derive(Eq, Hash, EqIgnoreSpan)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
pub struct ImportStarAsSpecifier {
pub span: Span,
pub local: Ident,
}
/// e.g. local = foo, imported = None `import { foo } from 'mod.js'`
/// e.g. local = bar, imported = Some(foo) for `import { foo as bar } from
/// 'mod.js'`
#[ast_node("ImportSpecifier")]
#[derive(Eq, Hash, EqIgnoreSpan)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
pub struct ImportNamedSpecifier {
pub span: Span,
pub local: Ident,
#[cfg_attr(feature = "serde-impl", serde(default))]
pub imported: Option<ModuleExportName>,
#[cfg_attr(feature = "serde-impl", serde(default))]
pub is_type_only: bool,
}
#[ast_node]
#[derive(Eq, Hash, Is, EqIgnoreSpan)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
pub enum ExportSpecifier {
#[tag("ExportNamespaceSpecifier")]
Namespace(ExportNamespaceSpecifier),
#[tag("ExportDefaultSpecifier")]
Default(ExportDefaultSpecifier),
#[tag("ExportSpecifier")]
Named(ExportNamedSpecifier),
}
/// `export * as foo from 'src';`
#[ast_node("ExportNamespaceSpecifier")]
#[derive(Eq, Hash, EqIgnoreSpan)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
pub struct ExportNamespaceSpecifier {
pub span: Span,
pub name: ModuleExportName,
}
// export v from 'mod';
#[ast_node("ExportDefaultSpecifier")]
#[derive(Eq, Hash, EqIgnoreSpan)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
pub struct ExportDefaultSpecifier {
#[span]
pub exported: Ident,
}
#[ast_node("ExportSpecifier")]
#[derive(Eq, Hash, EqIgnoreSpan)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
pub struct ExportNamedSpecifier {
pub span: Span,
/// `foo` in `export { foo as bar }`
pub orig: ModuleExportName,
/// `Some(bar)` in `export { foo as bar }`
#[cfg_attr(feature = "serde-impl", serde(default))]
pub exported: Option<ModuleExportName>,
/// `type` in `export { type foo as bar }`
#[cfg_attr(feature = "serde-impl", serde(default))]
pub is_type_only: bool,
}
#[ast_node]
#[derive(Eq, Hash, EqIgnoreSpan)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
// https://tc39.es/ecma262/#prod-ModuleExportName
pub enum ModuleExportName {
#[tag("Identifier")]
Ident(Ident),
#[tag("StringLiteral")]
Str(Str),
}

View file

@ -0,0 +1,228 @@
use string_enum::StringEnum;
use swc_common::EqIgnoreSpan;
#[derive(StringEnum, Clone, Copy, Eq, PartialEq, PartialOrd, Ord, Hash, EqIgnoreSpan)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[cfg_attr(
any(feature = "rkyv-impl"),
derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)
)]
#[cfg_attr(feature = "rkyv-impl", archive(check_bytes))]
#[cfg_attr(feature = "rkyv-impl", archive_attr(repr(u32)))]
pub enum BinaryOp {
/// `==`
EqEq,
/// `!=`
NotEq,
/// `===`
EqEqEq,
/// `!==`
NotEqEq,
/// `<`
Lt,
/// `<=`
LtEq,
/// `>`
Gt,
/// `>=`
GtEq,
/// `<<`
LShift,
/// `>>`
RShift,
/// `>>>`
ZeroFillRShift,
/// `+`
Add,
/// `-`
Sub,
/// `*`
Mul,
/// `/`
Div,
/// `%`
Mod,
/// `|`
BitOr,
/// `^`
BitXor,
/// `&`
BitAnd,
/// `||`
LogicalOr,
/// `&&`
LogicalAnd,
/// `in`
In,
/// `instanceof`
InstanceOf,
/// `**`
Exp,
/// `??`
NullishCoalescing,
}
impl BinaryOp {
pub fn precedence(self) -> u8 {
match self {
BinaryOp::EqEq => 6,
BinaryOp::NotEq => 6,
BinaryOp::EqEqEq => 6,
BinaryOp::NotEqEq => 6,
BinaryOp::Lt => 7,
BinaryOp::LtEq => 7,
BinaryOp::Gt => 7,
BinaryOp::GtEq => 7,
BinaryOp::LShift => 8,
BinaryOp::RShift => 8,
BinaryOp::ZeroFillRShift => 8,
BinaryOp::Add => 9,
BinaryOp::Sub => 9,
BinaryOp::Mul => 10,
BinaryOp::Div => 10,
BinaryOp::Mod => 10,
BinaryOp::BitOr => 3,
BinaryOp::BitXor => 4,
BinaryOp::BitAnd => 5,
BinaryOp::LogicalOr => 1,
BinaryOp::LogicalAnd => 2,
BinaryOp::In => 7,
BinaryOp::InstanceOf => 7,
BinaryOp::Exp => 11,
BinaryOp::NullishCoalescing => 1,
}
}
pub fn may_short_circuit(&self) -> bool {
matches!(self, op!("??") | op!("||") | op!("&&"))
}
}
#[derive(StringEnum, Clone, Copy, Eq, PartialEq, PartialOrd, Ord, Hash, EqIgnoreSpan)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[cfg_attr(
any(feature = "rkyv-impl"),
derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)
)]
#[cfg_attr(feature = "rkyv-impl", archive(check_bytes))]
#[cfg_attr(feature = "rkyv-impl", archive_attr(repr(u32)))]
pub enum AssignOp {
/// `=`
Assign,
/// `+=`
AddAssign,
/// `-=`
SubAssign,
/// `*=`
MulAssign,
/// `/=`
DivAssign,
/// `%=`
ModAssign,
/// `<<=`
LShiftAssign,
/// `>>=`
RShiftAssign,
/// `>>>=`
ZeroFillRShiftAssign,
/// `|=`
BitOrAssign,
/// `^=`
BitXorAssign,
/// `&=`
BitAndAssign,
/// `**=`
ExpAssign,
/// `&&=`
AndAssign,
/// `||=`
OrAssign,
/// `??=`
NullishAssign,
}
impl AssignOp {
pub fn to_update(self) -> Option<BinaryOp> {
match self {
op!("=") => None,
op!("+=") => Some(op!(bin, "+")),
op!("-=") => Some(op!(bin, "-")),
op!("*=") => Some(op!("*")),
op!("/=") => Some(op!("/")),
op!("%=") => Some(op!("%")),
op!("<<=") => Some(op!("<<")),
op!(">>=") => Some(op!(">>")),
op!(">>>=") => Some(op!(">>>")),
op!("|=") => Some(op!("|")),
op!("&=") => Some(op!("&")),
op!("^=") => Some(op!("^")),
op!("**=") => Some(op!("**")),
op!("&&=") => Some(op!("&&")),
op!("||=") => Some(op!("||")),
op!("??=") => Some(op!("??")),
}
}
pub fn may_short_circuit(&self) -> bool {
matches!(self, op!("??=") | op!("||=") | op!("&&="))
}
}
#[derive(StringEnum, Clone, Copy, Eq, PartialEq, PartialOrd, Ord, Hash, EqIgnoreSpan)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[cfg_attr(
any(feature = "rkyv-impl"),
derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)
)]
#[cfg_attr(feature = "rkyv-impl", archive(check_bytes))]
#[cfg_attr(feature = "rkyv-impl", archive_attr(repr(u32)))]
pub enum UpdateOp {
/// `++`
PlusPlus,
/// `--`
MinusMinus,
}
#[derive(StringEnum, Clone, Copy, Eq, PartialEq, PartialOrd, Ord, Hash, EqIgnoreSpan)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[cfg_attr(
any(feature = "rkyv-impl"),
derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)
)]
#[cfg_attr(feature = "rkyv-impl", archive(check_bytes))]
#[cfg_attr(feature = "rkyv-impl", archive_attr(repr(u32)))]
pub enum UnaryOp {
/// `-`
Minus,
/// `+`
Plus,
/// `!`
Bang,
/// `~`
Tilde,
/// `typeof`
TypeOf,
/// `void`
Void,
/// `delete`
Delete,
}

View file

@ -0,0 +1,176 @@
use is_macro::Is;
use swc_common::{ast_node, util::take::Take, EqIgnoreSpan, Span, DUMMY_SP};
use crate::{
expr::Expr,
ident::{BindingIdent, Ident},
prop::PropName,
typescript::TsTypeAnn,
Id, Invalid,
};
#[ast_node(no_clone)]
#[derive(Eq, Hash, Is, EqIgnoreSpan)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
pub enum Pat {
#[tag("Identifier")]
Ident(BindingIdent),
#[tag("ArrayPattern")]
Array(ArrayPat),
#[tag("RestElement")]
Rest(RestPat),
#[tag("ObjectPattern")]
Object(ObjectPat),
#[tag("AssignmentPattern")]
Assign(AssignPat),
#[tag("Invalid")]
Invalid(Invalid),
/// Only for for-in / for-of loops. This is *syntactically* valid.
#[tag("*")]
Expr(Box<Expr>),
}
// Implement Clone without inline to avoid multiple copies of the
// implementation.
impl Clone for Pat {
fn clone(&self) -> Self {
use Pat::*;
match self {
Ident(p) => Ident(p.clone()),
Array(p) => Array(p.clone()),
Rest(p) => Rest(p.clone()),
Object(p) => Object(p.clone()),
Assign(p) => Assign(p.clone()),
Invalid(p) => Invalid(p.clone()),
Expr(p) => Expr(p.clone()),
}
}
}
impl Take for Pat {
fn dummy() -> Self {
Pat::Invalid(Invalid { span: DUMMY_SP })
}
}
bridge_pat_from!(BindingIdent, Ident);
bridge_pat_from!(BindingIdent, Id);
macro_rules! pat_to_other {
($T:ty) => {
bridge_from!(crate::Param, crate::Pat, $T);
bridge_from!(Box<crate::Pat>, crate::Pat, $T);
bridge_from!(crate::PatOrExpr, crate::Pat, $T);
};
}
pat_to_other!(BindingIdent);
pat_to_other!(ArrayPat);
pat_to_other!(ObjectPat);
pat_to_other!(AssignPat);
pat_to_other!(RestPat);
#[ast_node("ArrayPattern")]
#[derive(Eq, Hash, EqIgnoreSpan)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
pub struct ArrayPat {
pub span: Span,
#[cfg_attr(feature = "serde-impl", serde(rename = "elements"))]
pub elems: Vec<Option<Pat>>,
/// Only in an ambient context
#[cfg_attr(feature = "serde-impl", serde(rename = "optional"))]
pub optional: bool,
#[cfg_attr(feature = "serde-impl", serde(default, rename = "typeAnnotation"))]
pub type_ann: Option<Box<TsTypeAnn>>,
}
#[ast_node("ObjectPattern")]
#[derive(Eq, Hash, EqIgnoreSpan)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
pub struct ObjectPat {
pub span: Span,
#[cfg_attr(feature = "serde-impl", serde(rename = "properties"))]
pub props: Vec<ObjectPatProp>,
/// Only in an ambient context
#[cfg_attr(feature = "serde-impl", serde(rename = "optional"))]
pub optional: bool,
#[cfg_attr(feature = "serde-impl", serde(default, rename = "typeAnnotation"))]
pub type_ann: Option<Box<TsTypeAnn>>,
}
#[ast_node("AssignmentPattern")]
#[derive(Eq, Hash, EqIgnoreSpan)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
pub struct AssignPat {
pub span: Span,
pub left: Box<Pat>,
pub right: Box<Expr>,
}
/// EsTree `RestElement`
#[ast_node("RestElement")]
#[derive(Eq, Hash, EqIgnoreSpan)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
pub struct RestPat {
pub span: Span,
#[cfg_attr(feature = "serde-impl", serde(rename = "rest"))]
pub dot3_token: Span,
#[cfg_attr(feature = "serde-impl", serde(rename = "argument"))]
pub arg: Box<Pat>,
#[cfg_attr(feature = "serde-impl", serde(default, rename = "typeAnnotation"))]
pub type_ann: Option<Box<TsTypeAnn>>,
}
#[ast_node]
#[derive(Eq, Hash, Is, EqIgnoreSpan)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
pub enum ObjectPatProp {
#[tag("KeyValuePatternProperty")]
KeyValue(KeyValuePatProp),
#[tag("AssignmentPatternProperty")]
Assign(AssignPatProp),
#[tag("RestElement")]
Rest(RestPat),
}
/// `{key: value}`
#[ast_node("KeyValuePatternProperty")]
#[derive(Eq, Hash, EqIgnoreSpan)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
pub struct KeyValuePatProp {
#[span(lo)]
pub key: PropName,
#[span(hi)]
pub value: Box<Pat>,
}
/// `{key}` or `{key = value}`
#[ast_node("AssignmentPatternProperty")]
#[derive(Eq, Hash, EqIgnoreSpan)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
pub struct AssignPatProp {
pub span: Span,
pub key: Ident,
#[cfg_attr(feature = "serde-impl", serde(default))]
pub value: Option<Box<Expr>>,
}

View file

@ -0,0 +1,158 @@
use is_macro::Is;
use swc_common::{ast_node, util::take::Take, EqIgnoreSpan, Span, DUMMY_SP};
use crate::{
expr::Expr,
function::Function,
ident::Ident,
lit::{BigInt, Number, Str},
pat::Pat,
stmt::BlockStmt,
typescript::TsTypeAnn,
Id, MemberProp,
};
#[ast_node]
#[derive(Eq, Hash, Is, EqIgnoreSpan)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
pub enum Prop {
/// `a` in `{ a, }`
#[tag("Identifier")]
Shorthand(Ident),
/// `key: value` in `{ key: value, }`
#[tag("KeyValueProperty")]
KeyValue(KeyValueProp),
/// This is **invalid** for object literal.
#[tag("AssignmentProperty")]
Assign(AssignProp),
#[tag("GetterProperty")]
Getter(GetterProp),
#[tag("SetterProperty")]
Setter(SetterProp),
#[tag("MethodProperty")]
Method(MethodProp),
}
#[ast_node("KeyValueProperty")]
#[derive(Eq, Hash, EqIgnoreSpan)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
pub struct KeyValueProp {
#[span(lo)]
pub key: PropName,
#[span(hi)]
pub value: Box<Expr>,
}
#[ast_node("AssignmentProperty")]
#[derive(Eq, Hash, EqIgnoreSpan)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
pub struct AssignProp {
#[span(lo)]
pub key: Ident,
#[span(hi)]
pub value: Box<Expr>,
}
#[ast_node("GetterProperty")]
#[derive(Eq, Hash, EqIgnoreSpan)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
pub struct GetterProp {
pub span: Span,
pub key: PropName,
#[cfg_attr(feature = "serde-impl", serde(default, rename = "typeAnnotation"))]
pub type_ann: Option<Box<TsTypeAnn>>,
#[cfg_attr(feature = "serde-impl", serde(default))]
pub body: Option<BlockStmt>,
}
#[ast_node("SetterProperty")]
#[derive(Eq, Hash, EqIgnoreSpan)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
pub struct SetterProp {
pub span: Span,
pub key: PropName,
pub param: Box<Pat>,
#[cfg_attr(feature = "serde-impl", serde(default))]
pub body: Option<BlockStmt>,
}
#[ast_node("MethodProperty")]
#[derive(Eq, Hash, EqIgnoreSpan)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
pub struct MethodProp {
pub key: PropName,
#[cfg_attr(feature = "serde-impl", serde(flatten))]
#[span]
pub function: Box<Function>,
}
#[ast_node]
#[derive(Eq, Hash, Is, EqIgnoreSpan)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
pub enum PropName {
#[tag("Identifier")]
Ident(Ident),
/// String literal.
#[tag("StringLiteral")]
Str(Str),
/// Numeric literal.
#[tag("NumericLiteral")]
Num(Number),
#[tag("Computed")]
Computed(ComputedPropName),
#[tag("BigIntLiteral")]
BigInt(BigInt),
}
bridge_from!(PropName, Ident, Id);
impl Take for PropName {
fn dummy() -> Self {
PropName::Ident(Take::dummy())
}
}
impl From<PropName> for MemberProp {
fn from(p: PropName) -> Self {
match p {
PropName::Ident(p) => MemberProp::Ident(p),
PropName::Computed(p) => MemberProp::Computed(p),
PropName::Str(p) => MemberProp::Computed(ComputedPropName {
span: DUMMY_SP,
expr: p.into(),
}),
PropName::Num(p) => MemberProp::Computed(ComputedPropName {
span: DUMMY_SP,
expr: p.into(),
}),
PropName::BigInt(p) => MemberProp::Computed(ComputedPropName {
span: DUMMY_SP,
expr: p.into(),
}),
}
}
}
#[ast_node("Computed")]
#[derive(Eq, Hash, EqIgnoreSpan)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
pub struct ComputedPropName {
/// Span including `[` and `]`.
pub span: Span,
#[cfg_attr(feature = "serde-impl", serde(rename = "expression"))]
pub expr: Box<Expr>,
}
impl Take for ComputedPropName {
fn dummy() -> Self {
Self {
span: DUMMY_SP,
expr: Take::dummy(),
}
}
}

View file

@ -0,0 +1,158 @@
use std::{rc::Rc, sync::Arc};
use swc_common::{BytePos, SourceMap, SourceMapper, SourceMapperDyn, Span, Spanned};
use crate::list::ListFormat;
pub trait SpanExt: Spanned {
#[inline]
fn is_synthesized(&self) -> bool {
false
}
fn starts_on_new_line(&self, format: ListFormat) -> bool {
format.intersects(ListFormat::PreferNewLine)
}
/// Gets a custom text range to use when emitting comments.
fn comment_range(&self) -> Span {
//TODO
self.span()
}
}
impl<T: Spanned> SpanExt for T {}
pub trait SourceMapperExt {
fn get_code_map(&self) -> &dyn SourceMapper;
fn is_on_same_line(&self, _lo: BytePos, _hi: BytePos) -> bool {
// let cm = self.get_code_map();
// let lo = cm.lookup_char_pos(lo);
// let hi = cm.lookup_char_pos(hi);
// lo.line == hi.line && lo.file.name_hash == hi.file.name_hash
false
}
fn should_write_separating_line_terminator(
&self,
prev: Option<Span>,
next: Option<Span>,
format: ListFormat,
) -> bool {
if format.contains(ListFormat::MultiLine) {
return true;
}
if format.contains(ListFormat::PreserveLines) {
if let (Some(prev), Some(next)) = (prev, next) {
if prev.is_synthesized() || next.is_synthesized() {
return prev.starts_on_new_line(format) || next.starts_on_new_line(format);
}
return !self.is_on_same_line(prev.hi(), next.lo());
} else {
return false;
}
}
false
}
fn should_write_leading_line_terminator(
&self,
parent_node: Span,
first_child: Option<Span>,
format: ListFormat,
) -> bool {
if format.contains(ListFormat::MultiLine) {
return true;
}
if format.contains(ListFormat::PreserveLines) {
if format.contains(ListFormat::PreferNewLine) {
return true;
}
if first_child.is_none() {
return !self.is_on_same_line(parent_node.lo(), parent_node.hi());
}
let first_child = first_child.unwrap();
if parent_node.is_synthesized() || first_child.is_synthesized() {
return first_child.starts_on_new_line(format);
}
!self.is_on_same_line(parent_node.lo(), first_child.lo())
} else {
false
}
}
fn should_write_closing_line_terminator(
&self,
parent_node: Span,
last_child: Option<Span>,
format: ListFormat,
) -> bool {
if format.contains(ListFormat::MultiLine) {
return (format & ListFormat::NoTrailingNewLine) == ListFormat::None;
}
if format.contains(ListFormat::PreserveLines) {
if format.contains(ListFormat::PreferNewLine) {
return true;
}
if last_child.is_none() {
return !self.is_on_same_line(parent_node.lo(), parent_node.hi());
}
let last_child = last_child.unwrap();
if parent_node.is_synthesized() || last_child.is_synthesized() {
last_child.starts_on_new_line(format)
} else {
!self.is_on_same_line(parent_node.hi(), last_child.hi())
}
} else {
false
}
}
}
impl SourceMapperExt for SourceMap {
fn get_code_map(&self) -> &dyn SourceMapper {
self
}
}
impl SourceMapperExt for dyn SourceMapper {
fn get_code_map(&self) -> &dyn SourceMapper {
self
}
}
impl SourceMapperExt for Arc<SourceMapperDyn> {
fn get_code_map(&self) -> &dyn SourceMapper {
&**self
}
}
impl SourceMapperExt for Rc<SourceMapperDyn> {
fn get_code_map(&self) -> &dyn SourceMapper {
&**self
}
}
impl SourceMapperExt for Arc<SourceMap> {
fn get_code_map(&self) -> &dyn SourceMapper {
&**self
}
}
impl SourceMapperExt for Rc<SourceMap> {
fn get_code_map(&self) -> &dyn SourceMapper {
&**self
}
}

View file

@ -0,0 +1,423 @@
use is_macro::Is;
use swc_common::{ast_node, util::take::Take, EqIgnoreSpan, Span, DUMMY_SP};
use crate::{
decl::{Decl, VarDecl},
expr::Expr,
ident::Ident,
pat::Pat,
UsingDecl,
};
/// Use when only block statements are allowed.
#[ast_node("BlockStatement")]
#[derive(Eq, Hash, EqIgnoreSpan)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
pub struct BlockStmt {
/// Span including the braces.
pub span: Span,
pub stmts: Vec<Stmt>,
}
impl Take for BlockStmt {
fn dummy() -> Self {
BlockStmt {
span: DUMMY_SP,
stmts: vec![],
}
}
}
#[ast_node(no_clone)]
#[derive(Eq, Hash, Is, EqIgnoreSpan)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
pub enum Stmt {
#[tag("BlockStatement")]
Block(BlockStmt),
#[tag("EmptyStatement")]
Empty(EmptyStmt),
#[tag("DebuggerStatement")]
Debugger(DebuggerStmt),
#[tag("WithStatement")]
With(WithStmt),
#[tag("ReturnStatement")]
#[is(name = "return_stmt")]
Return(ReturnStmt),
#[tag("LabeledStatement")]
Labeled(LabeledStmt),
#[tag("BreakStatement")]
#[is(name = "break_stmt")]
Break(BreakStmt),
#[tag("ContinueStatement")]
#[is(name = "continue_stmt")]
Continue(ContinueStmt),
#[tag("IfStatement")]
#[is(name = "if_stmt")]
If(IfStmt),
#[tag("SwitchStatement")]
Switch(SwitchStmt),
#[tag("ThrowStatement")]
Throw(ThrowStmt),
/// A try statement. If handler is null then finalizer must be a BlockStmt.
#[tag("TryStatement")]
#[is(name = "try_stmt")]
Try(Box<TryStmt>),
#[tag("WhileStatement")]
#[is(name = "while_stmt")]
While(WhileStmt),
#[tag("DoWhileStatement")]
DoWhile(DoWhileStmt),
#[tag("ForStatement")]
#[is(name = "for_stmt")]
For(ForStmt),
#[tag("ForInStatement")]
ForIn(ForInStmt),
#[tag("ForOfStatement")]
ForOf(ForOfStmt),
#[tag("ClassDeclaration")]
#[tag("FunctionDeclaration")]
#[tag("VariableDeclaration")]
#[tag("TsInterfaceDeclaration")]
#[tag("TsTypeAliasDeclaration")]
#[tag("TsEnumDeclaration")]
#[tag("TsModuleDeclaration")]
Decl(Decl),
#[tag("ExpressionStatement")]
Expr(ExprStmt),
}
// Memory layout depedns on the version of rustc.
// #[cfg(target_pointer_width = "64")]
// assert_eq_size!(Stmt, [u8; 56]);
// Implement Clone without inline to avoid multiple copies of the
// implementation.
impl Clone for Stmt {
fn clone(&self) -> Self {
use Stmt::*;
match self {
Block(s) => Block(s.clone()),
Empty(s) => Empty(s.clone()),
Debugger(s) => Debugger(s.clone()),
With(s) => With(s.clone()),
Return(s) => Return(s.clone()),
Labeled(s) => Labeled(s.clone()),
Break(s) => Break(s.clone()),
Continue(s) => Continue(s.clone()),
If(s) => If(s.clone()),
Switch(s) => Switch(s.clone()),
Throw(s) => Throw(s.clone()),
Try(s) => Try(s.clone()),
While(s) => While(s.clone()),
DoWhile(s) => DoWhile(s.clone()),
For(s) => For(s.clone()),
ForIn(s) => ForIn(s.clone()),
ForOf(s) => ForOf(s.clone()),
Decl(s) => Decl(s.clone()),
Expr(s) => Expr(s.clone()),
}
}
}
impl Take for Stmt {
fn dummy() -> Self {
Self::Empty(EmptyStmt { span: DUMMY_SP })
}
}
bridge_stmt_from!(Box<TryStmt>, TryStmt);
#[ast_node("ExpressionStatement")]
#[derive(Eq, Hash, EqIgnoreSpan)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
pub struct ExprStmt {
pub span: Span,
#[cfg_attr(feature = "serde-impl", serde(rename = "expression"))]
pub expr: Box<Expr>,
}
#[ast_node("EmptyStatement")]
#[derive(Eq, Hash, Copy, EqIgnoreSpan)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
pub struct EmptyStmt {
/// Span of semicolon.
pub span: Span,
}
#[ast_node("DebuggerStatement")]
#[derive(Eq, Hash, Copy, EqIgnoreSpan)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
pub struct DebuggerStmt {
pub span: Span,
}
#[ast_node("WithStatement")]
#[derive(Eq, Hash, EqIgnoreSpan)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
pub struct WithStmt {
pub span: Span,
#[cfg_attr(feature = "serde-impl", serde(rename = "object"))]
pub obj: Box<Expr>,
pub body: Box<Stmt>,
}
#[ast_node("ReturnStatement")]
#[derive(Eq, Hash, EqIgnoreSpan)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
pub struct ReturnStmt {
pub span: Span,
#[cfg_attr(feature = "serde-impl", serde(default, rename = "argument"))]
pub arg: Option<Box<Expr>>,
}
#[ast_node("LabeledStatement")]
#[derive(Eq, Hash, EqIgnoreSpan)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
pub struct LabeledStmt {
pub span: Span,
pub label: Ident,
pub body: Box<Stmt>,
}
#[ast_node("BreakStatement")]
#[derive(Eq, Hash, EqIgnoreSpan)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
pub struct BreakStmt {
pub span: Span,
#[cfg_attr(feature = "serde-impl", serde(default))]
pub label: Option<Ident>,
}
#[ast_node("ContinueStatement")]
#[derive(Eq, Hash, EqIgnoreSpan)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
pub struct ContinueStmt {
pub span: Span,
#[cfg_attr(feature = "serde-impl", serde(default))]
pub label: Option<Ident>,
}
#[ast_node("IfStatement")]
#[derive(Eq, Hash, EqIgnoreSpan)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
pub struct IfStmt {
pub span: Span,
pub test: Box<Expr>,
#[cfg_attr(feature = "serde-impl", serde(rename = "consequent"))]
pub cons: Box<Stmt>,
#[cfg_attr(feature = "serde-impl", serde(default, rename = "alternate"))]
pub alt: Option<Box<Stmt>>,
}
#[ast_node("SwitchStatement")]
#[derive(Eq, Hash, EqIgnoreSpan)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
pub struct SwitchStmt {
pub span: Span,
pub discriminant: Box<Expr>,
pub cases: Vec<SwitchCase>,
}
#[ast_node("ThrowStatement")]
#[derive(Eq, Hash, EqIgnoreSpan)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
pub struct ThrowStmt {
pub span: Span,
#[cfg_attr(feature = "serde-impl", serde(rename = "argument"))]
pub arg: Box<Expr>,
}
#[ast_node("TryStatement")]
#[derive(Eq, Hash, EqIgnoreSpan)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
pub struct TryStmt {
pub span: Span,
pub block: BlockStmt,
#[cfg_attr(feature = "serde-impl", serde(default))]
pub handler: Option<CatchClause>,
#[cfg_attr(feature = "serde-impl", serde(default))]
pub finalizer: Option<BlockStmt>,
}
#[ast_node("WhileStatement")]
#[derive(Eq, Hash, EqIgnoreSpan)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
pub struct WhileStmt {
pub span: Span,
pub test: Box<Expr>,
pub body: Box<Stmt>,
}
#[ast_node("DoWhileStatement")]
#[derive(Eq, Hash, EqIgnoreSpan)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
pub struct DoWhileStmt {
pub span: Span,
pub test: Box<Expr>,
pub body: Box<Stmt>,
}
#[ast_node("ForStatement")]
#[derive(Eq, Hash, EqIgnoreSpan)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
pub struct ForStmt {
pub span: Span,
#[cfg_attr(feature = "serde-impl", serde(default))]
pub init: Option<VarDeclOrExpr>,
#[cfg_attr(feature = "serde-impl", serde(default))]
pub test: Option<Box<Expr>>,
#[cfg_attr(feature = "serde-impl", serde(default))]
pub update: Option<Box<Expr>>,
pub body: Box<Stmt>,
}
#[ast_node("ForInStatement")]
#[derive(Eq, Hash, EqIgnoreSpan)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
pub struct ForInStmt {
pub span: Span,
pub left: ForHead,
pub right: Box<Expr>,
pub body: Box<Stmt>,
}
#[ast_node("ForOfStatement")]
#[derive(Eq, Hash, EqIgnoreSpan)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
pub struct ForOfStmt {
pub span: Span,
/// Span of the await token.
///
/// es2018
///
/// for-await-of statements, e.g., `for await (const x of xs) {`
#[cfg_attr(feature = "serde-impl", serde(default, rename = "await"))]
pub is_await: bool,
pub left: ForHead,
pub right: Box<Expr>,
pub body: Box<Stmt>,
}
impl Take for ForOfStmt {
fn dummy() -> Self {
ForOfStmt {
span: DUMMY_SP,
is_await: Default::default(),
left: Take::dummy(),
right: Take::dummy(),
body: Take::dummy(),
}
}
}
#[ast_node("SwitchCase")]
#[derive(Eq, Hash, EqIgnoreSpan)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
pub struct SwitchCase {
pub span: Span,
/// None for `default:`
#[cfg_attr(feature = "serde-impl", serde(default))]
pub test: Option<Box<Expr>>,
#[cfg_attr(feature = "serde-impl", serde(rename = "consequent"))]
pub cons: Vec<Stmt>,
}
impl Take for SwitchCase {
fn dummy() -> Self {
Self {
span: DUMMY_SP,
test: None,
cons: Vec::new(),
}
}
}
#[ast_node("CatchClause")]
#[derive(Eq, Hash, EqIgnoreSpan)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
pub struct CatchClause {
pub span: Span,
/// es2019
///
/// The param is null if the catch binding is omitted. E.g., try { foo() }
/// catch { bar() }
#[cfg_attr(feature = "serde-impl", serde(default))]
pub param: Option<Pat>,
pub body: BlockStmt,
}
/// A head for for-in and for-of loop.
#[ast_node]
#[derive(Eq, Hash, Is, EqIgnoreSpan)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
pub enum ForHead {
#[tag("VariableDeclaration")]
VarDecl(Box<VarDecl>),
#[tag("UsingDeclaration")]
UsingDecl(Box<UsingDecl>),
#[tag("*")]
Pat(Box<Pat>),
}
bridge_from!(ForHead, Box<VarDecl>, VarDecl);
bridge_from!(ForHead, Box<Pat>, Pat);
impl Take for ForHead {
fn dummy() -> Self {
ForHead::Pat(Take::dummy())
}
}
#[ast_node]
#[derive(Eq, Hash, Is, EqIgnoreSpan)]
#[allow(variant_size_differences)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
pub enum VarDeclOrExpr {
#[tag("VariableDeclaration")]
VarDecl(Box<VarDecl>),
#[tag("*")]
Expr(Box<Expr>),
}
bridge_from!(VarDeclOrExpr, Box<VarDecl>, VarDecl);
bridge_from!(VarDeclOrExpr, Box<Expr>, Expr);
impl Take for VarDeclOrExpr {
fn dummy() -> Self {
VarDeclOrExpr::Expr(Take::dummy())
}
}

File diff suppressed because it is too large Load diff