mirror of
https://github.com/swc-project/swc.git
synced 2024-12-23 13:51:19 +03:00
Extract utils from swc_ecma_transforms (#575)
swc_ecma_transforms: - extract utils
This commit is contained in:
parent
6eb066166f
commit
5503cde085
@ -13,7 +13,8 @@ edition = "2018"
|
||||
ast = { package = "swc_ecma_ast", path ="./ast" }
|
||||
codegen = { package = "swc_ecma_codegen", path ="./codegen" }
|
||||
parser = { package = "swc_ecma_parser", path ="./parser", features = ["verify"] }
|
||||
transforms = { package = "swc_ecma_transforms", path ="./transforms" }
|
||||
preset_env = { package = "swc_ecma_preset_env", path ="preset_env" }
|
||||
utils = { package = "swc_ecma_utils", path ="./utils" }
|
||||
transforms = { package = "swc_ecma_transforms", path ="./transforms" }
|
||||
|
||||
[dev-dependencies]
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "swc_ecma_transforms"
|
||||
version = "0.4.0"
|
||||
version = "0.5.0"
|
||||
authors = ["강동윤 <kdy1997.dev@gmail.com>"]
|
||||
license = "Apache-2.0/MIT"
|
||||
repository = "https://github.com/swc-project/swc.git"
|
||||
@ -12,6 +12,7 @@ edition = "2018"
|
||||
swc_atoms = { version = "0.2.0", path ="../../atoms" }
|
||||
swc_common = { version = "0.4.2", path ="../../common" }
|
||||
ast = { package = "swc_ecma_ast", version = "0.14.0", path ="../ast" }
|
||||
utils = { package = "swc_ecma_utils", version = "0.1.0", path ="../utils" }
|
||||
swc_ecma_parser = { version = "0.16", path ="../parser", features = ["verify"] }
|
||||
chashmap = "2.2.0"
|
||||
either = "1.5"
|
||||
|
@ -4,6 +4,7 @@ use crate::{
|
||||
};
|
||||
use ast::*;
|
||||
use swc_common::{Fold, FoldWith, Spanned, Visit, VisitWith, DUMMY_SP};
|
||||
use utils::quote_ident;
|
||||
|
||||
/// Compile ES2015 arrow functions to ES5
|
||||
///
|
||||
|
@ -4,6 +4,7 @@ use ast::*;
|
||||
use std::iter;
|
||||
use swc_atoms::JsWord;
|
||||
use swc_common::{Fold, FoldWith, Mark, Visit, VisitWith, DUMMY_SP};
|
||||
use utils::quote_ident;
|
||||
|
||||
pub(super) struct SuperCallFinder {
|
||||
mode: Option<SuperFoldingMode>,
|
||||
|
@ -4,6 +4,7 @@ use ast::*;
|
||||
use std::iter;
|
||||
use swc_atoms::js_word;
|
||||
use swc_common::{Fold, FoldWith, Mark, Span, Spanned, DUMMY_SP};
|
||||
use utils::quote_ident;
|
||||
|
||||
/// Process function body.
|
||||
///
|
||||
|
@ -1,13 +1,13 @@
|
||||
use crate::util::{
|
||||
options::{CM, SESSION},
|
||||
prepend_stmts, DropSpan,
|
||||
};
|
||||
use ast::*;
|
||||
use lazy_static::lazy_static;
|
||||
use scoped_tls::scoped_thread_local;
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
use swc_common::{FileName, Fold, FoldWith, Mark, Span, DUMMY_SP};
|
||||
use swc_ecma_parser::{lexer::Lexer, Parser, SourceFileInput};
|
||||
use utils::{
|
||||
options::{CM, SESSION},
|
||||
prepend_stmts, quote_ident, quote_str, DropSpan,
|
||||
};
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! enable_helper {
|
||||
|
@ -8,6 +8,9 @@
|
||||
#![cfg_attr(test, feature(test))]
|
||||
#![recursion_limit = "1024"]
|
||||
|
||||
#[macro_use]
|
||||
extern crate utils;
|
||||
|
||||
pub use self::{const_modules::const_modules, fixer::fixer, hygiene::hygiene, resolver::resolver};
|
||||
|
||||
#[macro_use]
|
||||
@ -33,4 +36,6 @@ pub mod react;
|
||||
mod resolver;
|
||||
pub mod scope;
|
||||
pub mod typescript;
|
||||
pub mod util;
|
||||
pub mod util {
|
||||
pub use utils::*;
|
||||
}
|
||||
|
@ -1,16 +1,3 @@
|
||||
/// Shortcut for `quote_ident!(span.apply_mark(Mark::fresh(Mark::root())), s)`
|
||||
macro_rules! private_ident {
|
||||
($s:expr) => {
|
||||
private_ident!(::swc_common::DUMMY_SP, $s)
|
||||
};
|
||||
($span:expr, $s:expr) => {{
|
||||
use swc_common::Mark;
|
||||
let mark = Mark::fresh(Mark::root());
|
||||
let span = $span.apply_mark(mark);
|
||||
::ast::Ident::new($s.into(), span)
|
||||
}};
|
||||
}
|
||||
|
||||
macro_rules! external_name {
|
||||
("typeof") => {
|
||||
"_typeof"
|
||||
@ -57,109 +44,3 @@ macro_rules! helper {
|
||||
helper_expr!($span, $field_name, $s).as_callee()
|
||||
}};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! quote_ident {
|
||||
($s:expr) => {
|
||||
quote_ident!(::swc_common::DUMMY_SP, $s)
|
||||
};
|
||||
($span:expr, $s:expr) => {{
|
||||
::ast::Ident::new($s.into(), $span)
|
||||
}};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! quote_str {
|
||||
($s:expr) => {
|
||||
quote_str!(::swc_common::DUMMY_SP, $s)
|
||||
};
|
||||
($span:expr, $s:expr) => {{
|
||||
::ast::Str {
|
||||
span: $span,
|
||||
value: $s.into(),
|
||||
has_escape: false,
|
||||
}
|
||||
}};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! quote_expr {
|
||||
($span:expr, null) => {{
|
||||
use ast::*;
|
||||
Expr::Lit(Lit::Null(Null { span: $span }))
|
||||
}};
|
||||
|
||||
($span:expr, undefined) => {{
|
||||
box Expr::Ident(Ident::new(js_word!("undefined"), $span))
|
||||
}};
|
||||
}
|
||||
|
||||
/// Creates a member expression.
|
||||
///
|
||||
/// # Usage
|
||||
/// ```rust,ignore
|
||||
/// member_expr!(span, Function.bind.apply);
|
||||
/// ```
|
||||
///
|
||||
/// Returns Box<Expr>
|
||||
#[macro_export]
|
||||
macro_rules! member_expr {
|
||||
($span:expr, $first:ident) => {{
|
||||
use ast::Expr;
|
||||
box Expr::Ident(quote_ident!($span, stringify!($first)))
|
||||
}};
|
||||
|
||||
($span:expr, $first:ident . $($rest:tt)+) => {{
|
||||
let obj = member_expr!($span, $first);
|
||||
|
||||
member_expr!(@EXT, $span, obj, $($rest)* )
|
||||
}};
|
||||
|
||||
(@EXT, $span:expr, $obj:expr, $first:ident . $($rest:tt)* ) => {{
|
||||
let prop = member_expr!($span, $first);
|
||||
|
||||
member_expr!(@EXT, $span, box Expr::Member(MemberExpr{
|
||||
span: ::swc_common::DUMMY_SP,
|
||||
obj: ExprOrSuper::Expr($obj),
|
||||
computed: false,
|
||||
prop,
|
||||
}), $($rest)*)
|
||||
}};
|
||||
|
||||
(@EXT, $span:expr, $obj:expr, $first:ident) => {{
|
||||
use ast::*;
|
||||
let prop = member_expr!($span, $first);
|
||||
|
||||
box Expr::Member(MemberExpr{
|
||||
span: ::swc_common::DUMMY_SP,
|
||||
obj: ExprOrSuper::Expr($obj),
|
||||
computed: false,
|
||||
prop,
|
||||
})
|
||||
}};
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use ast::*;
|
||||
use swc_common::DUMMY_SP as span;
|
||||
#[test]
|
||||
fn quote_member_expr() {
|
||||
let expr: Box<Expr> = member_expr!(span, Function.prototype.bind);
|
||||
|
||||
testing::assert_eq_ignore_span!(
|
||||
expr,
|
||||
box Expr::Member(MemberExpr {
|
||||
span,
|
||||
obj: ExprOrSuper::Expr(box Expr::Member(MemberExpr {
|
||||
span,
|
||||
obj: ExprOrSuper::Expr(member_expr!(span, Function)),
|
||||
computed: false,
|
||||
prop: member_expr!(span, prototype),
|
||||
})),
|
||||
computed: false,
|
||||
prop: member_expr!(span, bind),
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
|
19
ecmascript/utils/Cargo.toml
Normal file
19
ecmascript/utils/Cargo.toml
Normal file
@ -0,0 +1,19 @@
|
||||
[package]
|
||||
name = "swc_ecma_utils"
|
||||
version = "0.1.0"
|
||||
authors = ["강동윤 <kdy1997.dev@gmail.com>"]
|
||||
edition = "2018"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
ast = { package = "swc_ecma_ast", version = "0.14.0", path ="../ast" }
|
||||
swc_atoms = { version = "0.2.0", path ="../../atoms" }
|
||||
swc_common = { version = "0.4.2", path ="../../common" }
|
||||
swc_ecma_parser = { version = "0.16", path ="../parser", features = ["verify"] }
|
||||
lazy_static = "1"
|
||||
scoped-tls = "1"
|
||||
unicode-xid = "0.2"
|
||||
|
||||
[dev-dependencies]
|
||||
testing = { version = "0.4", path ="../../testing" }
|
@ -1,10 +1,10 @@
|
||||
use crate::util::{prepend_stmts, ExprFactory};
|
||||
use crate::{prepend_stmts, ExprFactory};
|
||||
use ast::*;
|
||||
use std::iter;
|
||||
use swc_common::{Fold, FoldWith, DUMMY_SP};
|
||||
|
||||
#[allow(clippy::vec_box)]
|
||||
pub(crate) fn inject_after_super(mut c: Constructor, exprs: Vec<Box<Expr>>) -> Constructor {
|
||||
pub fn inject_after_super(mut c: Constructor, exprs: Vec<Box<Expr>>) -> Constructor {
|
||||
// Allow using super multiple time
|
||||
let mut folder = Injector {
|
||||
exprs: &exprs,
|
@ -1,3 +1,8 @@
|
||||
#![feature(box_patterns)]
|
||||
#![feature(box_syntax)]
|
||||
#![feature(try_trait)]
|
||||
#![feature(specialization)]
|
||||
|
||||
pub use self::{
|
||||
factory::ExprFactory,
|
||||
ident::{id, Id},
|
||||
@ -10,7 +15,7 @@ pub use self::{
|
||||
},
|
||||
Purity::{MayBeImpure, Pure},
|
||||
};
|
||||
use crate::util::ident::IdentLike;
|
||||
use crate::ident::IdentLike;
|
||||
use ast::*;
|
||||
use scoped_tls::scoped_thread_local;
|
||||
use std::{
|
||||
@ -26,14 +31,16 @@ use swc_common::{
|
||||
};
|
||||
use unicode_xid::UnicodeXID;
|
||||
|
||||
pub(crate) mod constructor;
|
||||
#[macro_use]
|
||||
mod macros;
|
||||
pub mod constructor;
|
||||
mod factory;
|
||||
pub mod ident;
|
||||
pub(crate) mod options;
|
||||
pub mod options;
|
||||
mod value;
|
||||
pub(crate) mod var;
|
||||
pub mod var;
|
||||
|
||||
pub(crate) struct ThisVisitor {
|
||||
pub struct ThisVisitor {
|
||||
found: bool,
|
||||
}
|
||||
|
||||
@ -63,7 +70,7 @@ impl Visit<FnDecl> for ThisVisitor {
|
||||
fn visit(&mut self, _: &FnDecl) {}
|
||||
}
|
||||
|
||||
pub(crate) fn contains_this_expr<N>(body: &N) -> bool
|
||||
pub fn contains_this_expr<N>(body: &N) -> bool
|
||||
where
|
||||
ThisVisitor: Visit<N>,
|
||||
{
|
||||
@ -72,7 +79,7 @@ where
|
||||
visitor.found
|
||||
}
|
||||
|
||||
pub(crate) fn contains_ident_ref<'a, N>(body: &N, ident: &'a Ident) -> bool
|
||||
pub fn contains_ident_ref<'a, N>(body: &N, ident: &'a Ident) -> bool
|
||||
where
|
||||
N: VisitWith<IdentFinder<'a>>,
|
||||
{
|
||||
@ -84,7 +91,7 @@ where
|
||||
visitor.found
|
||||
}
|
||||
|
||||
pub(crate) struct IdentFinder<'a> {
|
||||
pub struct IdentFinder<'a> {
|
||||
ident: &'a Ident,
|
||||
found: bool,
|
||||
}
|
||||
@ -213,7 +220,7 @@ impl<T> IsEmpty for Vec<T> {
|
||||
}
|
||||
|
||||
/// Extracts hoisted variables
|
||||
pub(crate) fn extract_var_ids<T: VisitWith<Hoister>>(node: &T) -> Vec<Ident> {
|
||||
pub fn extract_var_ids<T: VisitWith<Hoister>>(node: &T) -> Vec<Ident> {
|
||||
let mut v = Hoister { vars: vec![] };
|
||||
node.visit_with(&mut v);
|
||||
v.vars
|
||||
@ -275,7 +282,7 @@ impl StmtExt for Box<Stmt> {
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) struct Hoister {
|
||||
pub struct Hoister {
|
||||
vars: Vec<Ident>,
|
||||
}
|
||||
|
||||
@ -1013,7 +1020,7 @@ impl Add for Purity {
|
||||
}
|
||||
|
||||
/// Cast to javascript's int32
|
||||
pub(crate) fn to_int32(d: f64) -> i32 {
|
||||
pub fn to_int32(d: f64) -> i32 {
|
||||
let id = d as i32;
|
||||
if id as f64 == d {
|
||||
// This covers -0.0 as well
|
||||
@ -1036,7 +1043,7 @@ pub(crate) fn to_int32(d: f64) -> i32 {
|
||||
l as i32
|
||||
}
|
||||
|
||||
// pub(crate) fn to_u32(_d: f64) -> u32 {
|
||||
// pub fn to_u32(_d: f64) -> u32 {
|
||||
// // if (Double.isNaN(d) || Double.isInfinite(d) || d == 0) {
|
||||
// // return 0;
|
||||
// // }
|
||||
@ -1055,13 +1062,13 @@ pub(crate) fn to_int32(d: f64) -> i32 {
|
||||
// unimplemented!("to_u32")
|
||||
// }
|
||||
|
||||
pub(crate) fn has_rest_pat<T: VisitWith<RestPatVisitor>>(node: &T) -> bool {
|
||||
pub fn has_rest_pat<T: VisitWith<RestPatVisitor>>(node: &T) -> bool {
|
||||
let mut v = RestPatVisitor { found: false };
|
||||
node.visit_with(&mut v);
|
||||
v.found
|
||||
}
|
||||
|
||||
pub(crate) struct RestPatVisitor {
|
||||
pub struct RestPatVisitor {
|
||||
found: bool,
|
||||
}
|
||||
|
||||
@ -1071,7 +1078,7 @@ impl Visit<RestPat> for RestPatVisitor {
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn is_literal<T>(node: &T) -> bool
|
||||
pub fn is_literal<T>(node: &T) -> bool
|
||||
where
|
||||
T: VisitWith<LiteralVisitor>,
|
||||
{
|
||||
@ -1080,7 +1087,7 @@ where
|
||||
}
|
||||
|
||||
#[inline(never)]
|
||||
pub(crate) fn calc_literal_cost<T>(e: &T, allow_non_json_value: bool) -> (bool, usize)
|
||||
pub fn calc_literal_cost<T>(e: &T, allow_non_json_value: bool) -> (bool, usize)
|
||||
where
|
||||
T: VisitWith<LiteralVisitor>,
|
||||
{
|
||||
@ -1094,7 +1101,7 @@ where
|
||||
(v.is_lit, v.cost)
|
||||
}
|
||||
|
||||
pub(crate) struct LiteralVisitor {
|
||||
pub struct LiteralVisitor {
|
||||
is_lit: bool,
|
||||
cost: usize,
|
||||
allow_non_json_value: bool,
|
||||
@ -1257,7 +1264,7 @@ pub fn alias_if_required(expr: &Expr, default: &str) -> (Ident, bool) {
|
||||
(alias_ident_for(expr, default), true)
|
||||
}
|
||||
|
||||
pub(crate) fn prop_name_to_expr(p: PropName) -> Expr {
|
||||
pub fn prop_name_to_expr(p: PropName) -> Expr {
|
||||
match p {
|
||||
PropName::Ident(i) => Expr::Ident(i),
|
||||
PropName::Str(s) => Expr::Lit(Lit::Str(s)),
|
||||
@ -1268,7 +1275,7 @@ pub(crate) fn prop_name_to_expr(p: PropName) -> Expr {
|
||||
/// Simillar to `prop_name_to_expr`, but used for value position.
|
||||
///
|
||||
/// e.g. value from `{ key: value }`
|
||||
pub(crate) fn prop_name_to_expr_value(p: PropName) -> Expr {
|
||||
pub fn prop_name_to_expr_value(p: PropName) -> Expr {
|
||||
match p {
|
||||
PropName::Ident(i) => Expr::Lit(Lit::Str(Str {
|
||||
span: i.span,
|
||||
@ -1320,7 +1327,7 @@ pub fn default_constructor(has_super: bool) -> Constructor {
|
||||
}
|
||||
|
||||
/// Check if `e` is `...arguments`
|
||||
pub(crate) fn is_rest_arguments(e: &ExprOrSpread) -> bool {
|
||||
pub fn is_rest_arguments(e: &ExprOrSpread) -> bool {
|
||||
match *e {
|
||||
ExprOrSpread {
|
||||
spread: Some(..),
|
||||
@ -1335,7 +1342,7 @@ pub(crate) fn is_rest_arguments(e: &ExprOrSpread) -> bool {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn undefined(span: Span) -> Box<Expr> {
|
||||
pub fn undefined(span: Span) -> Box<Expr> {
|
||||
box Expr::Unary(UnaryExpr {
|
||||
span,
|
||||
op: op!("void"),
|
||||
@ -1429,11 +1436,11 @@ impl IdentExt for Ident {
|
||||
}
|
||||
|
||||
/// Finds all idents of variable
|
||||
pub(crate) struct DestructuringFinder<'a, I: IdentLike> {
|
||||
pub struct DestructuringFinder<'a, I: IdentLike> {
|
||||
pub found: &'a mut Vec<I>,
|
||||
}
|
||||
|
||||
pub(crate) fn find_ids<T, I: IdentLike>(node: &T) -> Vec<I>
|
||||
pub fn find_ids<T, I: IdentLike>(node: &T) -> Vec<I>
|
||||
where
|
||||
T: for<'any> VisitWith<DestructuringFinder<'any, I>>,
|
||||
{
|
||||
@ -1463,7 +1470,7 @@ impl<'a, I: IdentLike> Visit<Ident> for DestructuringFinder<'a, I> {
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn is_valid_ident(s: &JsWord) -> bool {
|
||||
pub fn is_valid_ident(s: &JsWord) -> bool {
|
||||
if s.len() == 0 {
|
||||
return false;
|
||||
}
|
||||
@ -1471,14 +1478,14 @@ pub(crate) fn is_valid_ident(s: &JsWord) -> bool {
|
||||
UnicodeXID::is_xid_start(first) && s.chars().skip(1).all(UnicodeXID::is_xid_continue)
|
||||
}
|
||||
|
||||
pub(crate) fn drop_span<T>(t: T) -> T
|
||||
pub fn drop_span<T>(t: T) -> T
|
||||
where
|
||||
T: FoldWith<DropSpan>,
|
||||
{
|
||||
t.fold_with(&mut DropSpan)
|
||||
}
|
||||
|
||||
pub(crate) struct DropSpan;
|
||||
pub struct DropSpan;
|
||||
impl Fold<Span> for DropSpan {
|
||||
fn fold(&mut self, _: Span) -> Span {
|
||||
DUMMY_SP
|
||||
@ -1486,7 +1493,7 @@ impl Fold<Span> for DropSpan {
|
||||
}
|
||||
|
||||
/// Finds usage of `ident`
|
||||
pub(crate) struct UsageFinder<'a> {
|
||||
pub struct UsageFinder<'a> {
|
||||
ident: &'a Ident,
|
||||
found: bool,
|
||||
}
|
||||
@ -1510,7 +1517,7 @@ impl<'a> Visit<Ident> for UsageFinder<'a> {
|
||||
}
|
||||
|
||||
impl<'a> UsageFinder<'a> {
|
||||
pub(crate) fn find<N>(ident: &'a Ident, node: &N) -> bool
|
||||
pub fn find<N>(ident: &'a Ident, node: &N) -> bool
|
||||
where
|
||||
N: VisitWith<Self>,
|
||||
{
|
||||
@ -1527,7 +1534,7 @@ scoped_thread_local!(pub static HANDLER: Handler);
|
||||
scoped_thread_local!(pub static COMMENTS: Comments);
|
||||
|
||||
/// make a new expression which evaluates `val` preserving side effects, if any.
|
||||
pub(crate) fn preserve_effects<I>(span: Span, val: Expr, exprs: I) -> Expr
|
||||
pub fn preserve_effects<I>(span: Span, val: Expr, exprs: I) -> Expr
|
||||
where
|
||||
I: IntoIterator<Item = Box<Expr>>,
|
||||
{
|
119
ecmascript/utils/src/macros.rs
Normal file
119
ecmascript/utils/src/macros.rs
Normal file
@ -0,0 +1,119 @@
|
||||
/// Shortcut for `quote_ident!(span.apply_mark(Mark::fresh(Mark::root())), s)`
|
||||
#[macro_export]
|
||||
macro_rules! private_ident {
|
||||
($s:expr) => {
|
||||
private_ident!(::swc_common::DUMMY_SP, $s)
|
||||
};
|
||||
($span:expr, $s:expr) => {{
|
||||
use swc_common::Mark;
|
||||
let mark = Mark::fresh(Mark::root());
|
||||
let span = $span.apply_mark(mark);
|
||||
::ast::Ident::new($s.into(), span)
|
||||
}};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! quote_ident {
|
||||
($s:expr) => {
|
||||
quote_ident!(::swc_common::DUMMY_SP, $s)
|
||||
};
|
||||
($span:expr, $s:expr) => {{
|
||||
::ast::Ident::new($s.into(), $span)
|
||||
}};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! quote_str {
|
||||
($s:expr) => {
|
||||
quote_str!(::swc_common::DUMMY_SP, $s)
|
||||
};
|
||||
($span:expr, $s:expr) => {{
|
||||
::ast::Str {
|
||||
span: $span,
|
||||
value: $s.into(),
|
||||
has_escape: false,
|
||||
}
|
||||
}};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! quote_expr {
|
||||
($span:expr, null) => {{
|
||||
use ast::*;
|
||||
Expr::Lit(Lit::Null(Null { span: $span }))
|
||||
}};
|
||||
|
||||
($span:expr, undefined) => {{
|
||||
box Expr::Ident(Ident::new(js_word!("undefined"), $span))
|
||||
}};
|
||||
}
|
||||
|
||||
/// Creates a member expression.
|
||||
///
|
||||
/// # Usage
|
||||
/// ```rust,ignore
|
||||
/// member_expr!(span, Function.bind.apply);
|
||||
/// ```
|
||||
///
|
||||
/// Returns Box<Expr>
|
||||
#[macro_export]
|
||||
macro_rules! member_expr {
|
||||
($span:expr, $first:ident) => {{
|
||||
use ast::Expr;
|
||||
box Expr::Ident(quote_ident!($span, stringify!($first)))
|
||||
}};
|
||||
|
||||
($span:expr, $first:ident . $($rest:tt)+) => {{
|
||||
let obj = member_expr!($span, $first);
|
||||
|
||||
member_expr!(@EXT, $span, obj, $($rest)* )
|
||||
}};
|
||||
|
||||
(@EXT, $span:expr, $obj:expr, $first:ident . $($rest:tt)* ) => {{
|
||||
let prop = member_expr!($span, $first);
|
||||
|
||||
member_expr!(@EXT, $span, box Expr::Member(MemberExpr{
|
||||
span: ::swc_common::DUMMY_SP,
|
||||
obj: ExprOrSuper::Expr($obj),
|
||||
computed: false,
|
||||
prop,
|
||||
}), $($rest)*)
|
||||
}};
|
||||
|
||||
(@EXT, $span:expr, $obj:expr, $first:ident) => {{
|
||||
use ast::*;
|
||||
let prop = member_expr!($span, $first);
|
||||
|
||||
box Expr::Member(MemberExpr{
|
||||
span: ::swc_common::DUMMY_SP,
|
||||
obj: ExprOrSuper::Expr($obj),
|
||||
computed: false,
|
||||
prop,
|
||||
})
|
||||
}};
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use ast::*;
|
||||
use swc_common::DUMMY_SP as span;
|
||||
#[test]
|
||||
fn quote_member_expr() {
|
||||
let expr: Box<Expr> = member_expr!(span, Function.prototype.bind);
|
||||
|
||||
testing::assert_eq_ignore_span!(
|
||||
expr,
|
||||
box Expr::Member(MemberExpr {
|
||||
span,
|
||||
obj: ExprOrSuper::Expr(box Expr::Member(MemberExpr {
|
||||
span,
|
||||
obj: ExprOrSuper::Expr(member_expr!(span, Function)),
|
||||
computed: false,
|
||||
prop: member_expr!(span, prototype),
|
||||
})),
|
||||
computed: false,
|
||||
prop: member_expr!(span, bind),
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
@ -7,9 +7,8 @@ use swc_common::{
|
||||
use swc_ecma_parser::Session;
|
||||
|
||||
lazy_static! {
|
||||
pub(crate) static ref CM: Arc<SourceMap> =
|
||||
{ Arc::new(SourceMap::new(FilePathMapping::empty())) };
|
||||
pub(crate) static ref HANDLER: Handler =
|
||||
pub static ref CM: Arc<SourceMap> = { Arc::new(SourceMap::new(FilePathMapping::empty())) };
|
||||
pub static ref HANDLER: Handler =
|
||||
{ Handler::with_tty_emitter(ColorConfig::Always, false, true, Some(CM.clone())) };
|
||||
pub(crate) static ref SESSION: Session<'static> = { Session { handler: &*HANDLER } };
|
||||
pub static ref SESSION: Session<'static> = { Session { handler: &*HANDLER } };
|
||||
}
|
@ -2,7 +2,7 @@ use ast::*;
|
||||
use swc_atoms::JsWord;
|
||||
use swc_common::{SyntaxContext, Visit, VisitWith};
|
||||
|
||||
pub(crate) struct VarCollector<'a> {
|
||||
pub struct VarCollector<'a> {
|
||||
pub to: &'a mut Vec<(JsWord, SyntaxContext)>,
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user