mirror of
https://github.com/swc-project/swc.git
synced 2024-10-05 12:49:21 +03:00
Improve performance of swc (#992)
swc_ecma_parser: - Make macros uses match instead of `PartialEq` swc_ecma_codegen: - Move panic condition
This commit is contained in:
parent
decac0c052
commit
e3faea25b6
@ -1653,7 +1653,7 @@ impl<'a> Emitter<'a> {
|
||||
Pat::Ident(ref n) => emit!(n),
|
||||
Pat::Object(ref n) => emit!(n),
|
||||
Pat::Rest(ref n) => emit!(n),
|
||||
Pat::Invalid(..) => unimplemented!("emit Pat::Invalid"),
|
||||
Pat::Invalid(..) => invalid_pat(),
|
||||
}
|
||||
}
|
||||
|
||||
@ -2416,3 +2416,9 @@ fn escape(s: &str) -> Cow<str> {
|
||||
.replace("\0", "\\0"),
|
||||
)
|
||||
}
|
||||
|
||||
#[cold]
|
||||
#[inline(never)]
|
||||
fn invalid_pat() -> ! {
|
||||
unimplemented!("emit Pat::Invalid")
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "swc_ecma_parser"
|
||||
version = "0.35.0"
|
||||
version = "0.35.1"
|
||||
authors = ["강동윤 <kdy1997.dev@gmail.com>"]
|
||||
license = "Apache-2.0/MIT"
|
||||
repository = "https://github.com/swc-project/swc.git"
|
||||
|
@ -260,13 +260,18 @@ impl<I: Tokens> Buffer<I> {
|
||||
|
||||
/// Returns current token.
|
||||
pub fn bump(&mut self) -> Token {
|
||||
#[cold]
|
||||
#[inline(never)]
|
||||
fn invalid_state() -> ! {
|
||||
unreachable!(
|
||||
"Current token is `None`. Parser should not call bump() without knowing current \
|
||||
token"
|
||||
)
|
||||
}
|
||||
|
||||
let prev = match self.cur.take() {
|
||||
Some(t) => t,
|
||||
|
||||
None => unreachable!(
|
||||
"Current token is `None`. Parser should not call bump()without knowing current \
|
||||
token"
|
||||
),
|
||||
None => invalid_state(),
|
||||
};
|
||||
self.prev_span = prev.span;
|
||||
|
||||
@ -313,7 +318,7 @@ impl<I: Tokens> Buffer<I> {
|
||||
}
|
||||
|
||||
/// Get current token. Returns `None` only on eof.
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub fn cur(&mut self) -> Option<&Token> {
|
||||
if self.cur.is_none() {
|
||||
self.bump_inner();
|
||||
@ -321,7 +326,7 @@ impl<I: Tokens> Buffer<I> {
|
||||
self.cur.as_ref().map(|item| &item.token)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub fn is(&mut self, expected: &Token) -> bool {
|
||||
match self.cur() {
|
||||
Some(t) => *expected == *t,
|
||||
@ -329,7 +334,7 @@ impl<I: Tokens> Buffer<I> {
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub fn peeked_is(&mut self, expected: &Token) -> bool {
|
||||
match self.peek() {
|
||||
Some(t) => *expected == *t,
|
||||
@ -337,7 +342,7 @@ impl<I: Tokens> Buffer<I> {
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub fn eat(&mut self, expected: &Token) -> bool {
|
||||
let v = self.is(expected);
|
||||
if v {
|
||||
@ -346,13 +351,19 @@ impl<I: Tokens> Buffer<I> {
|
||||
v
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub fn eat_keyword(&mut self, kwd: Keyword) -> bool {
|
||||
self.eat(&Word(Word::Keyword(kwd)))
|
||||
match self.cur() {
|
||||
Some(Token::Word(Word::Keyword(k))) if *k == kwd => {
|
||||
self.bump();
|
||||
true
|
||||
}
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns start of current token.
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub fn cur_pos(&mut self) -> BytePos {
|
||||
let _ = self.cur();
|
||||
self.cur
|
||||
@ -364,7 +375,7 @@ impl<I: Tokens> Buffer<I> {
|
||||
})
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub fn cur_span(&self) -> Span {
|
||||
let data = self
|
||||
.cur
|
||||
@ -376,50 +387,50 @@ impl<I: Tokens> Buffer<I> {
|
||||
}
|
||||
|
||||
/// Returns last byte position of previous token.
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub fn last_pos(&self) -> BytePos {
|
||||
self.prev_span.hi
|
||||
}
|
||||
|
||||
/// Returns span of the previous token.
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub fn prev_span(&self) -> Span {
|
||||
self.prev_span
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub(crate) fn get_ctx(&self) -> Context {
|
||||
self.iter.ctx()
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub(crate) fn set_ctx(&mut self, ctx: Context) {
|
||||
self.iter.set_ctx(ctx);
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub fn syntax(&self) -> Syntax {
|
||||
self.iter.syntax()
|
||||
}
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub fn target(&self) -> JscTarget {
|
||||
self.iter.target()
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub(crate) fn set_expr_allowed(&mut self, allow: bool) {
|
||||
self.iter.set_expr_allowed(allow)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub(crate) fn token_context(&self) -> &lexer::TokenContexts {
|
||||
self.iter.token_context()
|
||||
}
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub(crate) fn token_context_mut(&mut self) -> &mut lexer::TokenContexts {
|
||||
self.iter.token_context_mut()
|
||||
}
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub(crate) fn set_token_context(&mut self, c: lexer::TokenContexts) {
|
||||
self.iter.set_token_context(c)
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
macro_rules! unexpected {
|
||||
($p:expr, $expected:literal) => {{
|
||||
let got = match cur!($p, false).ok() {
|
||||
let got = match $p.input.cur() {
|
||||
Some(v) => format!("{:?}", v),
|
||||
None => format!("<eof>"),
|
||||
};
|
||||
@ -43,14 +43,14 @@ macro_rules! is {
|
||||
}};
|
||||
|
||||
($p:expr,';') => {{
|
||||
$p.input.is(&Token::Semi)
|
||||
|| eof!($p)
|
||||
|| is!($p, '}')
|
||||
|| $p.input.had_line_break_before_cur()
|
||||
match $p.input.cur() {
|
||||
Some(&Token::Semi) | None | Some(&tok!('}')) => true,
|
||||
_ => $p.input.had_line_break_before_cur(),
|
||||
}
|
||||
}};
|
||||
|
||||
($p:expr, $t:tt) => {
|
||||
$p.input.is(&tok!($t))
|
||||
is_exact!($p, $t)
|
||||
};
|
||||
}
|
||||
|
||||
@ -83,7 +83,10 @@ macro_rules! peeked_is {
|
||||
}};
|
||||
|
||||
($p:expr, $t:tt) => {
|
||||
$p.input.peeked_is(&tok!($t))
|
||||
match peek!($p).ok() {
|
||||
Some(&token_including_semi!($t)) => true,
|
||||
_ => false,
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@ -107,7 +110,7 @@ macro_rules! is_one_of {
|
||||
macro_rules! assert_and_bump {
|
||||
($p:expr, $t:tt) => {{
|
||||
const TOKEN: &Token = &tok!($t);
|
||||
if cfg!(debug_assertions) && !$p.input.is(TOKEN) {
|
||||
if cfg!(debug_assertions) && !is!($p, $t) {
|
||||
unreachable!(
|
||||
"assertion failed: expected {:?}, got {:?}",
|
||||
TOKEN,
|
||||
@ -126,10 +129,14 @@ macro_rules! assert_and_bump {
|
||||
macro_rules! eat {
|
||||
($p:expr, ';') => {{
|
||||
log::trace!("eat(';'): cur={:?}", cur!($p, false));
|
||||
$p.input.eat(&Token::Semi)
|
||||
|| eof!($p)
|
||||
|| is!($p, '}')
|
||||
|| $p.input.had_line_break_before_cur()
|
||||
match $p.input.cur() {
|
||||
Some(&Token::Semi) => {
|
||||
$p.input.bump();
|
||||
true
|
||||
}
|
||||
None | Some(&tok!('}')) => true,
|
||||
_ => $p.input.had_line_break_before_cur(),
|
||||
}
|
||||
}};
|
||||
|
||||
($p:expr, $t:tt) => {{
|
||||
@ -144,8 +151,7 @@ macro_rules! eat {
|
||||
|
||||
macro_rules! eat_exact {
|
||||
($p:expr, $t:tt) => {{
|
||||
const TOKEN: &Token = &token_including_semi!($t);
|
||||
if $p.input.is(TOKEN) {
|
||||
if is_exact!($p, $t) {
|
||||
bump!($p);
|
||||
true
|
||||
} else {
|
||||
@ -156,8 +162,10 @@ macro_rules! eat_exact {
|
||||
|
||||
macro_rules! is_exact {
|
||||
($p:expr, $t:tt) => {{
|
||||
const TOKEN: &Token = &token_including_semi!($t);
|
||||
$p.input.is(TOKEN)
|
||||
match $p.input.cur() {
|
||||
Some(&token_including_semi!($t)) => true,
|
||||
_ => false,
|
||||
}
|
||||
}};
|
||||
}
|
||||
|
||||
@ -166,7 +174,7 @@ macro_rules! expect {
|
||||
($p:expr, $t:tt) => {{
|
||||
const TOKEN: &Token = &token_including_semi!($t);
|
||||
if !eat!($p, $t) {
|
||||
let cur = match cur!($p, false).ok() {
|
||||
let cur = match $p.input.cur() {
|
||||
Some(v) => format!("{:?}", v),
|
||||
None => format!("<eof>"),
|
||||
};
|
||||
@ -179,7 +187,7 @@ macro_rules! expect_exact {
|
||||
($p:expr, $t:tt) => {{
|
||||
const TOKEN: &Token = &token_including_semi!($t);
|
||||
if !eat_exact!($p, $t) {
|
||||
let cur = match cur!($p, false).ok() {
|
||||
let cur = match $p.input.cur() {
|
||||
Some(v) => format!("{:?}", v),
|
||||
None => format!("<eof>"),
|
||||
};
|
||||
|
@ -114,6 +114,7 @@ impl<'a, I: Tokens> Parser<I> {
|
||||
}
|
||||
|
||||
/// Parse with given closure
|
||||
#[inline(always)]
|
||||
pub(super) fn parse_with<F, Ret>(&mut self, f: F) -> PResult<Ret>
|
||||
where
|
||||
F: FnOnce(&mut Self) -> PResult<Ret>,
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "swc_ecma_transforms"
|
||||
version = "0.21.0"
|
||||
version = "0.21.1"
|
||||
authors = ["강동윤 <kdy1997.dev@gmail.com>"]
|
||||
license = "Apache-2.0/MIT"
|
||||
repository = "https://github.com/swc-project/swc.git"
|
||||
@ -37,6 +37,7 @@ serde_json = "1"
|
||||
smallvec = "1"
|
||||
is-macro = "0.1"
|
||||
log = "0.4.8"
|
||||
retain_mut = "=0.1.1"
|
||||
|
||||
[dev-dependencies]
|
||||
testing = { version = "0.9.0", path ="../../testing" }
|
||||
|
@ -1,7 +1,8 @@
|
||||
use self::side_effect::{ImportDetector, SideEffectVisitor};
|
||||
use crate::pass::RepeatedJsPass;
|
||||
use fxhash::FxHashSet;
|
||||
use std::{any::type_name, borrow::Cow};
|
||||
use retain_mut::RetainMut;
|
||||
use std::{any::type_name, borrow::Cow, mem::take};
|
||||
use swc_atoms::JsWord;
|
||||
use swc_common::{
|
||||
chain,
|
||||
@ -11,15 +12,12 @@ use swc_common::{
|
||||
};
|
||||
use swc_ecma_ast::*;
|
||||
use swc_ecma_utils::{find_ids, ident::IdentLike, Id, StmtLike};
|
||||
use swc_ecma_visit::{
|
||||
as_folder, noop_fold_type, noop_visit_mut_type, Fold, FoldWith, VisitMut, VisitWith,
|
||||
};
|
||||
use swc_ecma_visit::{as_folder, noop_visit_mut_type, VisitMut, VisitMutWith, VisitWith};
|
||||
|
||||
macro_rules! preserve {
|
||||
($name:ident, $T:ty) => {
|
||||
fn $name(&mut self, mut node: $T) -> $T {
|
||||
fn $name(&mut self, node: &mut $T) {
|
||||
node.span = node.span.apply_mark(self.config.used_mark);
|
||||
node
|
||||
}
|
||||
};
|
||||
}
|
||||
@ -56,14 +54,14 @@ pub fn dce<'a>(config: Config<'a>) -> impl RepeatedJsPass + 'a {
|
||||
let used_mark = config.used_mark;
|
||||
|
||||
chain!(
|
||||
Dce {
|
||||
as_folder(Dce {
|
||||
config,
|
||||
dropped: false,
|
||||
included: Default::default(),
|
||||
changed: false,
|
||||
marking_phase: false,
|
||||
decl_dropping_phase: false,
|
||||
},
|
||||
}),
|
||||
as_folder(UsedMarkRemover { used_mark })
|
||||
)
|
||||
}
|
||||
@ -133,89 +131,80 @@ impl Repeated for Dce<'_> {
|
||||
}
|
||||
}
|
||||
|
||||
impl Fold for Dce<'_> {
|
||||
noop_fold_type!();
|
||||
impl VisitMut for Dce<'_> {
|
||||
noop_visit_mut_type!();
|
||||
|
||||
preserve!(fold_debugger_stmt, DebuggerStmt);
|
||||
preserve!(fold_with_stmt, WithStmt);
|
||||
preserve!(fold_break_stmt, BreakStmt);
|
||||
preserve!(fold_continue_stmt, ContinueStmt);
|
||||
preserve!(visit_mut_debugger_stmt, DebuggerStmt);
|
||||
preserve!(visit_mut_with_stmt, WithStmt);
|
||||
preserve!(visit_mut_break_stmt, BreakStmt);
|
||||
preserve!(visit_mut_continue_stmt, ContinueStmt);
|
||||
|
||||
preserve!(fold_ts_export_assignment, TsExportAssignment);
|
||||
|
||||
fn fold_block_stmt(&mut self, node: BlockStmt) -> BlockStmt {
|
||||
fn visit_mut_block_stmt(&mut self, node: &mut BlockStmt) {
|
||||
if self.is_marked(node.span) {
|
||||
return node;
|
||||
return;
|
||||
}
|
||||
node.stmts.visit_mut_with(self);
|
||||
|
||||
let mut stmts = node.stmts.fold_with(self);
|
||||
|
||||
let mut span = node.span;
|
||||
if self.marking_phase || stmts.iter().any(|stmt| self.is_marked(stmt.span())) {
|
||||
span = span.apply_mark(self.config.used_mark);
|
||||
stmts = self.fold_in_marking_phase(stmts);
|
||||
if self.marking_phase || node.stmts.iter().any(|stmt| self.is_marked(stmt.span())) {
|
||||
node.span = node.span.apply_mark(self.config.used_mark);
|
||||
self.mark(&mut node.stmts);
|
||||
}
|
||||
|
||||
BlockStmt { span, stmts }
|
||||
}
|
||||
|
||||
fn fold_class_decl(&mut self, mut node: ClassDecl) -> ClassDecl {
|
||||
fn visit_mut_class_decl(&mut self, node: &mut ClassDecl) {
|
||||
if self.is_marked(node.span()) {
|
||||
return node;
|
||||
return;
|
||||
}
|
||||
|
||||
if self.marking_phase || self.included.contains(&node.ident.to_id()) {
|
||||
node.class.span = node.class.span.apply_mark(self.config.used_mark);
|
||||
node.class.super_class = self.fold_in_marking_phase(node.class.super_class);
|
||||
self.mark(&mut node.class.super_class);
|
||||
}
|
||||
|
||||
node.fold_children_with(self)
|
||||
node.visit_mut_children_with(self)
|
||||
}
|
||||
|
||||
fn fold_do_while_stmt(&mut self, mut node: DoWhileStmt) -> DoWhileStmt {
|
||||
fn visit_mut_do_while_stmt(&mut self, node: &mut DoWhileStmt) {
|
||||
if self.is_marked(node.span) {
|
||||
return node;
|
||||
return;
|
||||
}
|
||||
|
||||
node = node.fold_children_with(self);
|
||||
node.visit_mut_children_with(self);
|
||||
|
||||
if self.is_marked(node.test.span()) || self.is_marked(node.body.span()) {
|
||||
node.span = node.span.apply_mark(self.config.used_mark);
|
||||
|
||||
node.test = self.fold_in_marking_phase(node.test);
|
||||
node.body = self.fold_in_marking_phase(node.body);
|
||||
self.mark(&mut node.test);
|
||||
self.mark(&mut node.body);
|
||||
}
|
||||
|
||||
node
|
||||
}
|
||||
|
||||
fn fold_export_all(&mut self, mut node: ExportAll) -> ExportAll {
|
||||
fn visit_mut_export_all(&mut self, node: &mut ExportAll) {
|
||||
if self.is_marked(node.span) {
|
||||
return node;
|
||||
return;
|
||||
}
|
||||
node.span = node.span.apply_mark(self.config.used_mark);
|
||||
node
|
||||
}
|
||||
|
||||
fn fold_export_decl(&mut self, mut node: ExportDecl) -> ExportDecl {
|
||||
fn visit_mut_export_decl(&mut self, node: &mut ExportDecl) {
|
||||
if self.is_marked(node.span) {
|
||||
return node;
|
||||
return;
|
||||
}
|
||||
|
||||
let i = match node.decl {
|
||||
let i = match &mut node.decl {
|
||||
Decl::Class(ClassDecl { ref ident, .. }) | Decl::Fn(FnDecl { ref ident, .. }) => ident,
|
||||
|
||||
// Preserve types
|
||||
Decl::TsInterface(_) | Decl::TsTypeAlias(_) | Decl::TsEnum(_) | Decl::TsModule(_) => {
|
||||
node.span = node.span.apply_mark(self.config.used_mark);
|
||||
return node;
|
||||
return;
|
||||
}
|
||||
|
||||
// Preserve only exported variables
|
||||
Decl::Var(mut v) => {
|
||||
v.decls = v.decls.move_flat_map(|mut d| {
|
||||
Decl::Var(v) => {
|
||||
v.decls.retain_mut(|d| {
|
||||
if self.is_marked(d.span()) {
|
||||
return Some(d);
|
||||
return true;
|
||||
}
|
||||
|
||||
let names: Vec<Id> = find_ids(&d.name);
|
||||
@ -224,105 +213,91 @@ impl Fold for Dce<'_> {
|
||||
|| self.should_preserve_export(&name.0)
|
||||
{
|
||||
d.span = d.span.apply_mark(self.config.used_mark);
|
||||
d.init = self.fold_in_marking_phase(d.init);
|
||||
return Some(d);
|
||||
self.mark(&mut d.init);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if self.decl_dropping_phase {
|
||||
return None;
|
||||
return false;
|
||||
}
|
||||
Some(d)
|
||||
true
|
||||
});
|
||||
|
||||
if self.decl_dropping_phase && !v.decls.is_empty() {
|
||||
node.span = node.span.apply_mark(self.config.used_mark);
|
||||
}
|
||||
|
||||
node.decl = Decl::Var(v);
|
||||
|
||||
return node;
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
if self.should_preserve_export(&i.sym) {
|
||||
node.span = node.span.apply_mark(self.config.used_mark);
|
||||
node.decl = self.fold_in_marking_phase(node.decl);
|
||||
self.mark(&mut node.decl);
|
||||
}
|
||||
|
||||
node
|
||||
}
|
||||
|
||||
fn fold_export_default_decl(&mut self, mut node: ExportDefaultDecl) -> ExportDefaultDecl {
|
||||
fn visit_mut_export_default_decl(&mut self, node: &mut ExportDefaultDecl) {
|
||||
if self.is_marked(node.span) {
|
||||
return node;
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: Export only when it's required. (i.e. check self.used_exports)
|
||||
|
||||
node.span = node.span.apply_mark(self.config.used_mark);
|
||||
node.decl = self.fold_in_marking_phase(node.decl);
|
||||
|
||||
node
|
||||
self.mark(&mut node.decl);
|
||||
}
|
||||
|
||||
fn fold_export_default_expr(&mut self, mut node: ExportDefaultExpr) -> ExportDefaultExpr {
|
||||
fn visit_mut_export_default_expr(&mut self, node: &mut ExportDefaultExpr) {
|
||||
if self.is_marked(node.span) {
|
||||
return node;
|
||||
return;
|
||||
}
|
||||
|
||||
if self.should_preserve_export(&js_word!("default")) {
|
||||
node.span = node.span.apply_mark(self.config.used_mark);
|
||||
node.expr = self.fold_in_marking_phase(node.expr);
|
||||
self.mark(&mut node.expr);
|
||||
}
|
||||
|
||||
node
|
||||
}
|
||||
|
||||
fn fold_expr_stmt(&mut self, node: ExprStmt) -> ExprStmt {
|
||||
fn visit_mut_expr_stmt(&mut self, node: &mut ExprStmt) {
|
||||
log::debug!("ExprStmt ->");
|
||||
if self.is_marked(node.span) {
|
||||
return node;
|
||||
return;
|
||||
}
|
||||
|
||||
if self.should_include(&node.expr) {
|
||||
log::debug!("\tIncluded");
|
||||
let stmt = ExprStmt {
|
||||
span: node.span.apply_mark(self.config.used_mark),
|
||||
expr: self.fold_in_marking_phase(node.expr),
|
||||
};
|
||||
return stmt;
|
||||
node.span = node.span.apply_mark(self.config.used_mark);
|
||||
self.mark(&mut node.expr);
|
||||
return;
|
||||
}
|
||||
|
||||
node.fold_children_with(self)
|
||||
node.visit_mut_children_with(self)
|
||||
}
|
||||
|
||||
fn fold_fn_decl(&mut self, mut f: FnDecl) -> FnDecl {
|
||||
fn visit_mut_fn_decl(&mut self, mut f: &mut FnDecl) {
|
||||
if self.is_marked(f.span()) {
|
||||
return f;
|
||||
return;
|
||||
}
|
||||
|
||||
if self.marking_phase || self.included.contains(&f.ident.to_id()) {
|
||||
f.function.span = f.function.span.apply_mark(self.config.used_mark);
|
||||
f.function.params = self.fold_in_marking_phase(f.function.params);
|
||||
f.function.body = self.fold_in_marking_phase(f.function.body);
|
||||
return f;
|
||||
self.mark(&mut f.function.params);
|
||||
self.mark(&mut f.function.body);
|
||||
return;
|
||||
}
|
||||
|
||||
f.fold_children_with(self)
|
||||
f.visit_mut_children_with(self)
|
||||
}
|
||||
|
||||
fn fold_for_in_stmt(&mut self, mut node: ForInStmt) -> ForInStmt {
|
||||
fn visit_mut_for_in_stmt(&mut self, node: &mut ForInStmt) {
|
||||
if self.is_marked(node.span) {
|
||||
return node;
|
||||
return;
|
||||
}
|
||||
|
||||
node = ForInStmt {
|
||||
span: node.span,
|
||||
left: node.left,
|
||||
right: node.right.fold_with(self),
|
||||
body: node.body.fold_with(self),
|
||||
};
|
||||
node.right.visit_mut_with(self);
|
||||
node.body.visit_mut_with(self);
|
||||
|
||||
if self.should_include(&node.left)
|
||||
|| self.is_marked(node.left.span())
|
||||
@ -331,26 +306,19 @@ impl Fold for Dce<'_> {
|
||||
{
|
||||
node.span = node.span.apply_mark(self.config.used_mark);
|
||||
|
||||
node.left = self.fold_in_marking_phase(node.left);
|
||||
node.right = self.fold_in_marking_phase(node.right);
|
||||
node.body = self.fold_in_marking_phase(node.body);
|
||||
self.mark(&mut node.left);
|
||||
self.mark(&mut node.right);
|
||||
self.mark(&mut node.body);
|
||||
}
|
||||
|
||||
node
|
||||
}
|
||||
|
||||
fn fold_for_of_stmt(&mut self, mut node: ForOfStmt) -> ForOfStmt {
|
||||
fn visit_mut_for_of_stmt(&mut self, node: &mut ForOfStmt) {
|
||||
if self.is_marked(node.span) {
|
||||
return node;
|
||||
return;
|
||||
}
|
||||
|
||||
node = ForOfStmt {
|
||||
span: node.span,
|
||||
await_token: node.await_token,
|
||||
left: node.left,
|
||||
right: node.right.fold_with(self),
|
||||
body: node.body.fold_with(self),
|
||||
};
|
||||
node.right.visit_mut_with(self);
|
||||
node.body.visit_mut_with(self);
|
||||
|
||||
if self.should_include(&node.left)
|
||||
|| self.is_marked(node.left.span())
|
||||
@ -359,20 +327,18 @@ impl Fold for Dce<'_> {
|
||||
{
|
||||
node.span = node.span.apply_mark(self.config.used_mark);
|
||||
|
||||
node.left = self.fold_in_marking_phase(node.left);
|
||||
node.right = self.fold_in_marking_phase(node.right);
|
||||
node.body = self.fold_in_marking_phase(node.body);
|
||||
self.mark(&mut node.left);
|
||||
self.mark(&mut node.right);
|
||||
self.mark(&mut node.body);
|
||||
}
|
||||
|
||||
node
|
||||
}
|
||||
|
||||
fn fold_for_stmt(&mut self, mut node: ForStmt) -> ForStmt {
|
||||
fn visit_mut_for_stmt(&mut self, node: &mut ForStmt) {
|
||||
if self.is_marked(node.span) {
|
||||
return node;
|
||||
return;
|
||||
}
|
||||
|
||||
node = node.fold_children_with(self);
|
||||
node.visit_mut_children_with(self);
|
||||
|
||||
if node.test.is_none()
|
||||
|| self.is_marked(node.init.span())
|
||||
@ -382,18 +348,16 @@ impl Fold for Dce<'_> {
|
||||
{
|
||||
node.span = node.span.apply_mark(self.config.used_mark);
|
||||
|
||||
node.test = self.fold_in_marking_phase(node.test);
|
||||
node.init = self.fold_in_marking_phase(node.init);
|
||||
node.update = self.fold_in_marking_phase(node.update);
|
||||
node.body = self.fold_in_marking_phase(node.body);
|
||||
self.mark(&mut node.test);
|
||||
self.mark(&mut node.init);
|
||||
self.mark(&mut node.update);
|
||||
self.mark(&mut node.body);
|
||||
}
|
||||
|
||||
node
|
||||
}
|
||||
|
||||
fn fold_ident(&mut self, i: Ident) -> Ident {
|
||||
fn visit_mut_ident(&mut self, i: &mut Ident) {
|
||||
if self.is_marked(i.span) {
|
||||
return i;
|
||||
return;
|
||||
}
|
||||
|
||||
if self.marking_phase {
|
||||
@ -402,16 +366,14 @@ impl Fold for Dce<'_> {
|
||||
self.changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
i
|
||||
}
|
||||
|
||||
fn fold_if_stmt(&mut self, node: IfStmt) -> IfStmt {
|
||||
fn visit_mut_if_stmt(&mut self, node: &mut IfStmt) {
|
||||
if self.is_marked(node.span) {
|
||||
return node;
|
||||
return;
|
||||
}
|
||||
|
||||
let mut node: IfStmt = node.fold_children_with(self);
|
||||
node.visit_mut_children_with(self);
|
||||
|
||||
if self.is_marked(node.test.span())
|
||||
|| self.is_marked(node.cons.span())
|
||||
@ -419,28 +381,26 @@ impl Fold for Dce<'_> {
|
||||
{
|
||||
node.span = node.span.apply_mark(self.config.used_mark);
|
||||
|
||||
node.test = self.fold_in_marking_phase(node.test);
|
||||
node.cons = self.fold_in_marking_phase(node.cons);
|
||||
node.alt = self.fold_in_marking_phase(node.alt);
|
||||
self.mark(&mut node.test);
|
||||
self.mark(&mut node.cons);
|
||||
self.mark(&mut node.alt);
|
||||
}
|
||||
|
||||
node
|
||||
}
|
||||
|
||||
fn fold_import_decl(&mut self, mut import: ImportDecl) -> ImportDecl {
|
||||
fn visit_mut_import_decl(&mut self, mut import: &mut ImportDecl) {
|
||||
// Do not mark import as used while ignoring imports
|
||||
if !self.decl_dropping_phase {
|
||||
return import;
|
||||
return;
|
||||
}
|
||||
|
||||
if self.is_marked(import.span) {
|
||||
return import;
|
||||
return;
|
||||
}
|
||||
|
||||
// Side effect import
|
||||
if import.specifiers.is_empty() {
|
||||
import.span = import.span.apply_mark(self.config.used_mark);
|
||||
return import;
|
||||
return;
|
||||
}
|
||||
|
||||
// Drop unused imports.
|
||||
@ -450,41 +410,35 @@ impl Fold for Dce<'_> {
|
||||
if !import.specifiers.is_empty() {
|
||||
import.span = import.span.apply_mark(self.config.used_mark);
|
||||
}
|
||||
|
||||
import
|
||||
}
|
||||
|
||||
fn fold_labeled_stmt(&mut self, mut node: LabeledStmt) -> LabeledStmt {
|
||||
fn visit_mut_labeled_stmt(&mut self, node: &mut LabeledStmt) {
|
||||
if self.is_marked(node.span) {
|
||||
return node;
|
||||
return;
|
||||
}
|
||||
|
||||
node.body = node.body.fold_with(self);
|
||||
node.body.visit_mut_with(self);
|
||||
|
||||
if self.is_marked(node.body.span()) {
|
||||
node.span = node.span.apply_mark(self.config.used_mark);
|
||||
node.body = self.fold_in_marking_phase(node.body);
|
||||
self.mark(&mut node.body);
|
||||
}
|
||||
|
||||
node
|
||||
}
|
||||
|
||||
fn fold_member_expr(&mut self, mut e: MemberExpr) -> MemberExpr {
|
||||
fn visit_mut_member_expr(&mut self, e: &mut MemberExpr) {
|
||||
if self.is_marked(e.span()) {
|
||||
return e;
|
||||
return;
|
||||
}
|
||||
|
||||
e.obj = e.obj.fold_with(self);
|
||||
e.obj.visit_mut_with(self);
|
||||
if e.computed {
|
||||
e.prop = e.prop.fold_with(self);
|
||||
e.prop.visit_mut_with(self);
|
||||
}
|
||||
|
||||
e
|
||||
}
|
||||
|
||||
fn fold_named_export(&mut self, mut node: NamedExport) -> NamedExport {
|
||||
fn visit_mut_named_export(&mut self, node: &mut NamedExport) {
|
||||
if self.is_marked(node.span) {
|
||||
return node;
|
||||
return;
|
||||
}
|
||||
|
||||
// Export only when it's required.
|
||||
@ -498,46 +452,40 @@ impl Fold for Dce<'_> {
|
||||
|
||||
if !node.specifiers.is_empty() {
|
||||
node.span = node.span.apply_mark(self.config.used_mark);
|
||||
node.specifiers = self.fold_in_marking_phase(node.specifiers);
|
||||
self.mark(&mut node.specifiers);
|
||||
}
|
||||
|
||||
node
|
||||
}
|
||||
|
||||
fn fold_return_stmt(&mut self, mut node: ReturnStmt) -> ReturnStmt {
|
||||
fn visit_mut_return_stmt(&mut self, node: &mut ReturnStmt) {
|
||||
if self.is_marked(node.span) {
|
||||
return node;
|
||||
return;
|
||||
}
|
||||
|
||||
node.span = node.span.apply_mark(self.config.used_mark);
|
||||
node.arg = self.fold_in_marking_phase(node.arg);
|
||||
|
||||
node
|
||||
self.mark(&mut node.arg);
|
||||
}
|
||||
|
||||
fn fold_switch_case(&mut self, mut node: SwitchCase) -> SwitchCase {
|
||||
fn visit_mut_switch_case(&mut self, node: &mut SwitchCase) {
|
||||
if self.is_marked(node.span) {
|
||||
return node;
|
||||
return;
|
||||
}
|
||||
|
||||
node = node.fold_children_with(self);
|
||||
node.visit_mut_children_with(self);
|
||||
|
||||
if self.is_marked(node.test.span()) || node.cons.iter().any(|v| self.is_marked(v.span())) {
|
||||
node.span = node.span.apply_mark(self.config.used_mark);
|
||||
|
||||
node.test = self.fold_in_marking_phase(node.test);
|
||||
node.cons = self.fold_in_marking_phase(node.cons);
|
||||
self.mark(&mut node.test);
|
||||
self.mark(&mut node.cons);
|
||||
}
|
||||
|
||||
node
|
||||
}
|
||||
|
||||
fn fold_switch_stmt(&mut self, mut node: SwitchStmt) -> SwitchStmt {
|
||||
fn visit_mut_switch_stmt(&mut self, node: &mut SwitchStmt) {
|
||||
if self.is_marked(node.span) {
|
||||
return node;
|
||||
return;
|
||||
}
|
||||
|
||||
node = node.fold_children_with(self);
|
||||
node.visit_mut_children_with(self);
|
||||
|
||||
// TODO: Handle fallthrough
|
||||
// Drop useless switch case.
|
||||
@ -549,33 +497,29 @@ impl Fold for Dce<'_> {
|
||||
|| node.cases.iter().any(|case| self.is_marked(case.span))
|
||||
{
|
||||
node.span = node.span.apply_mark(self.config.used_mark);
|
||||
node.cases = self.fold_in_marking_phase(node.cases);
|
||||
self.mark(&mut node.cases);
|
||||
}
|
||||
|
||||
node
|
||||
}
|
||||
|
||||
fn fold_throw_stmt(&mut self, mut node: ThrowStmt) -> ThrowStmt {
|
||||
fn visit_mut_throw_stmt(&mut self, node: &mut ThrowStmt) {
|
||||
if self.is_marked(node.span) {
|
||||
return node;
|
||||
return;
|
||||
}
|
||||
node.span = node.span.apply_mark(self.config.used_mark);
|
||||
|
||||
let mut node = node.fold_children_with(self);
|
||||
node.visit_mut_children_with(self);
|
||||
|
||||
if self.is_marked(node.arg.span()) {
|
||||
node.arg = self.fold_in_marking_phase(node.arg)
|
||||
self.mark(&mut node.arg)
|
||||
}
|
||||
|
||||
node
|
||||
}
|
||||
|
||||
fn fold_try_stmt(&mut self, mut node: TryStmt) -> TryStmt {
|
||||
fn visit_mut_try_stmt(&mut self, node: &mut TryStmt) {
|
||||
if self.is_marked(node.span) {
|
||||
return node;
|
||||
return;
|
||||
}
|
||||
|
||||
node = node.fold_children_with(self);
|
||||
node.visit_mut_children_with(self);
|
||||
|
||||
if self.is_marked(node.block.span())
|
||||
|| self.is_marked(node.handler.span())
|
||||
@ -583,96 +527,87 @@ impl Fold for Dce<'_> {
|
||||
{
|
||||
node.span = node.span.apply_mark(self.config.used_mark);
|
||||
|
||||
node.block = self.fold_in_marking_phase(node.block);
|
||||
node.handler = self.fold_in_marking_phase(node.handler);
|
||||
node.finalizer = self.fold_in_marking_phase(node.finalizer);
|
||||
self.mark(&mut node.block);
|
||||
self.mark(&mut node.handler);
|
||||
self.mark(&mut node.finalizer);
|
||||
}
|
||||
|
||||
node
|
||||
}
|
||||
|
||||
fn fold_update_expr(&mut self, mut node: UpdateExpr) -> UpdateExpr {
|
||||
fn visit_mut_update_expr(&mut self, node: &mut UpdateExpr) {
|
||||
if self.is_marked(node.span) {
|
||||
return node;
|
||||
return;
|
||||
}
|
||||
|
||||
node.span = node.span.apply_mark(self.config.used_mark);
|
||||
node.arg = self.fold_in_marking_phase(node.arg);
|
||||
|
||||
node
|
||||
self.mark(&mut node.arg);
|
||||
}
|
||||
|
||||
fn fold_var_decl(&mut self, mut var: VarDecl) -> VarDecl {
|
||||
fn visit_mut_var_decl(&mut self, mut var: &mut VarDecl) {
|
||||
if self.is_marked(var.span) {
|
||||
return var;
|
||||
return;
|
||||
}
|
||||
|
||||
var = var.fold_children_with(self);
|
||||
var.visit_mut_children_with(self);
|
||||
|
||||
var.decls = var.decls.move_flat_map(|decl| {
|
||||
var.decls.retain_mut(|decl| {
|
||||
if self.is_marked(decl.span()) {
|
||||
return Some(decl);
|
||||
return true;
|
||||
}
|
||||
|
||||
if !self.should_include(&decl.name) {
|
||||
if self.decl_dropping_phase {
|
||||
return None;
|
||||
return false;
|
||||
}
|
||||
return Some(decl);
|
||||
return true;
|
||||
}
|
||||
|
||||
Some(VarDeclarator {
|
||||
span: decl.span.apply_mark(self.config.used_mark),
|
||||
init: self.fold_in_marking_phase(decl.init),
|
||||
name: self.fold_in_marking_phase(decl.name),
|
||||
..decl
|
||||
})
|
||||
decl.span = decl.span.apply_mark(self.config.used_mark);
|
||||
self.mark(&mut decl.init);
|
||||
self.mark(&mut decl.name);
|
||||
true
|
||||
});
|
||||
|
||||
if var.decls.is_empty() || !self.decl_dropping_phase {
|
||||
return var;
|
||||
return;
|
||||
}
|
||||
|
||||
return VarDecl {
|
||||
span: var.span.apply_mark(self.config.used_mark),
|
||||
..var
|
||||
};
|
||||
var.span = var.span.apply_mark(self.config.used_mark);
|
||||
}
|
||||
|
||||
fn fold_while_stmt(&mut self, mut node: WhileStmt) -> WhileStmt {
|
||||
fn visit_mut_while_stmt(&mut self, node: &mut WhileStmt) {
|
||||
if self.is_marked(node.span) {
|
||||
return node;
|
||||
return;
|
||||
}
|
||||
|
||||
node = node.fold_children_with(self);
|
||||
node.visit_mut_children_with(self);
|
||||
|
||||
if self.is_marked(node.test.span()) || self.is_marked(node.body.span()) {
|
||||
node.span = node.span.apply_mark(self.config.used_mark);
|
||||
|
||||
node.test = self.fold_in_marking_phase(node.test);
|
||||
node.body = self.fold_in_marking_phase(node.body);
|
||||
self.mark(&mut node.test);
|
||||
self.mark(&mut node.body);
|
||||
}
|
||||
|
||||
node
|
||||
}
|
||||
|
||||
fn fold_module_items(&mut self, n: Vec<ModuleItem>) -> Vec<ModuleItem> {
|
||||
self.fold_stmt_like(n)
|
||||
fn visit_mut_module_items(&mut self, n: &mut Vec<ModuleItem>) {
|
||||
self.visit_mut_stmt_like(n)
|
||||
}
|
||||
|
||||
fn fold_stmts(&mut self, n: Vec<Stmt>) -> Vec<Stmt> {
|
||||
self.fold_stmt_like(n)
|
||||
fn visit_mut_stmts(&mut self, n: &mut Vec<Stmt>) {
|
||||
self.visit_mut_stmt_like(n)
|
||||
}
|
||||
}
|
||||
|
||||
impl Dce<'_> {
|
||||
fn fold_stmt_like<T>(&mut self, mut items: Vec<T>) -> Vec<T>
|
||||
fn visit_mut_stmt_like<T>(&mut self, items: &mut Vec<T>)
|
||||
where
|
||||
T: StmtLike + FoldWith<Self> + Spanned + std::fmt::Debug,
|
||||
T: StmtLike + VisitMutWith<Self> + Spanned + std::fmt::Debug,
|
||||
T: for<'any> VisitWith<SideEffectVisitor<'any>> + VisitWith<ImportDetector>,
|
||||
Vec<T>: VisitMutWith<Self>,
|
||||
{
|
||||
if self.marking_phase {
|
||||
return items.move_map(|item| item.fold_with(self));
|
||||
items.visit_mut_children_with(self);
|
||||
return;
|
||||
}
|
||||
|
||||
let old = self.changed;
|
||||
@ -685,24 +620,20 @@ impl Dce<'_> {
|
||||
|
||||
self.changed = false;
|
||||
let mut idx = 0u32;
|
||||
items = items.move_map(|mut item| {
|
||||
let item = if preserved.contains(&idx) {
|
||||
item
|
||||
} else {
|
||||
if self.should_include(&item) {
|
||||
items.iter_mut().for_each(|item| {
|
||||
if !preserved.contains(&idx) {
|
||||
if self.should_include(&*item) {
|
||||
preserved.insert(idx);
|
||||
self.changed = true;
|
||||
item = item.fold_with(self);
|
||||
item.visit_mut_with(self);
|
||||
}
|
||||
item
|
||||
};
|
||||
}
|
||||
|
||||
idx += 1;
|
||||
item
|
||||
});
|
||||
|
||||
if !self.changed {
|
||||
items = items.move_map(|item| item.fold_with(self));
|
||||
items.visit_mut_children_with(self);
|
||||
}
|
||||
|
||||
if !self.changed {
|
||||
@ -712,8 +643,10 @@ impl Dce<'_> {
|
||||
|
||||
{
|
||||
let mut idx = 0;
|
||||
items = items.move_flat_map(|item| {
|
||||
let item = self.drop_unused_decls(item);
|
||||
let taken = take(items);
|
||||
// We use take because of try_into_stmt
|
||||
*items = taken.move_flat_map(|mut item| {
|
||||
self.drop_unused_decls(&mut item);
|
||||
let item = match item.try_into_stmt() {
|
||||
Ok(stmt) => match stmt {
|
||||
Stmt::Empty(..) => {
|
||||
@ -743,8 +676,6 @@ impl Dce<'_> {
|
||||
}
|
||||
|
||||
self.changed = old;
|
||||
|
||||
items
|
||||
}
|
||||
}
|
||||
|
||||
@ -800,28 +731,24 @@ impl Dce<'_> {
|
||||
// ret
|
||||
// }
|
||||
|
||||
pub fn fold_in_marking_phase<T>(&mut self, node: T) -> T
|
||||
pub fn mark<T>(&mut self, node: &mut T)
|
||||
where
|
||||
T: FoldWith<Self>,
|
||||
T: VisitMutWith<Self>,
|
||||
{
|
||||
let old = self.marking_phase;
|
||||
self.marking_phase = true;
|
||||
log::info!("Marking: {}", type_name::<T>());
|
||||
let node = node.fold_with(self);
|
||||
node.visit_mut_with(self);
|
||||
self.marking_phase = old;
|
||||
|
||||
node
|
||||
}
|
||||
|
||||
pub fn drop_unused_decls<T>(&mut self, node: T) -> T
|
||||
pub fn drop_unused_decls<T>(&mut self, node: &mut T)
|
||||
where
|
||||
T: FoldWith<Self>,
|
||||
T: VisitMutWith<Self>,
|
||||
{
|
||||
let old = self.decl_dropping_phase;
|
||||
self.decl_dropping_phase = true;
|
||||
let node = node.fold_with(self);
|
||||
node.visit_mut_with(self);
|
||||
self.decl_dropping_phase = old;
|
||||
|
||||
node
|
||||
}
|
||||
}
|
||||
|
@ -1,8 +1,8 @@
|
||||
use crate::{prepend_stmts, ExprFactory};
|
||||
use std::iter;
|
||||
use std::{iter, mem::replace};
|
||||
use swc_common::DUMMY_SP;
|
||||
use swc_ecma_ast::*;
|
||||
use swc_ecma_visit::{Fold, FoldWith};
|
||||
use swc_ecma_visit::{noop_fold_type, noop_visit_mut_type, Fold, FoldWith, VisitMut, VisitMutWith};
|
||||
|
||||
pub fn inject_after_super(mut c: Constructor, exprs: Vec<Box<Expr>>) -> Constructor {
|
||||
// Allow using super multiple time
|
||||
@ -28,6 +28,8 @@ struct Injector<'a> {
|
||||
}
|
||||
|
||||
impl<'a> Fold for Injector<'a> {
|
||||
noop_fold_type!();
|
||||
|
||||
fn fold_class(&mut self, c: Class) -> Class {
|
||||
c
|
||||
}
|
||||
@ -67,7 +69,7 @@ impl<'a> Fold for Injector<'a> {
|
||||
injected: false,
|
||||
exprs: self.exprs,
|
||||
};
|
||||
let stmt = stmt.fold_children_with(&mut folder);
|
||||
let mut stmt = stmt.fold_children_with(&mut folder);
|
||||
self.injected |= folder.injected;
|
||||
if folder.injected {
|
||||
buf.push(stmt);
|
||||
@ -77,7 +79,7 @@ impl<'a> Fold for Injector<'a> {
|
||||
exprs: self.exprs,
|
||||
injected_tmp: None,
|
||||
};
|
||||
let stmt = stmt.fold_with(&mut folder);
|
||||
stmt.visit_mut_with(&mut folder);
|
||||
|
||||
self.injected |= folder.injected;
|
||||
|
||||
@ -109,19 +111,17 @@ struct ExprInjector<'a> {
|
||||
injected_tmp: Option<Ident>,
|
||||
}
|
||||
|
||||
impl Fold for ExprInjector<'_> {
|
||||
fn fold_class(&mut self, c: Class) -> Class {
|
||||
let super_class = c.super_class.fold_with(self);
|
||||
impl VisitMut for ExprInjector<'_> {
|
||||
noop_visit_mut_type!();
|
||||
|
||||
Class { super_class, ..c }
|
||||
fn visit_mut_class(&mut self, c: &mut Class) {
|
||||
c.super_class.visit_mut_with(self);
|
||||
}
|
||||
|
||||
fn fold_constructor(&mut self, n: Constructor) -> Constructor {
|
||||
n
|
||||
}
|
||||
fn visit_mut_constructor(&mut self, _: &mut Constructor) {}
|
||||
|
||||
fn fold_expr(&mut self, expr: Expr) -> Expr {
|
||||
let expr = expr.fold_children_with(self);
|
||||
fn visit_mut_expr(&mut self, expr: &mut Expr) {
|
||||
expr.visit_mut_children_with(self);
|
||||
|
||||
match expr {
|
||||
Expr::Call(CallExpr {
|
||||
@ -134,8 +134,9 @@ impl Fold for ExprInjector<'_> {
|
||||
.unwrap_or_else(|| private_ident!("_temp")),
|
||||
);
|
||||
self.injected = true;
|
||||
let e = replace(expr, Expr::Invalid(Invalid { span: DUMMY_SP }));
|
||||
|
||||
Expr::Seq(SeqExpr {
|
||||
*expr = Expr::Seq(SeqExpr {
|
||||
span: DUMMY_SP,
|
||||
exprs: iter::once(Box::new(Expr::Assign(AssignExpr {
|
||||
span: DUMMY_SP,
|
||||
@ -143,7 +144,7 @@ impl Fold for ExprInjector<'_> {
|
||||
self.injected_tmp.as_ref().cloned().unwrap(),
|
||||
))),
|
||||
op: op!("="),
|
||||
right: Box::new(expr),
|
||||
right: Box::new(e),
|
||||
})))
|
||||
.chain(self.exprs.iter().cloned())
|
||||
.chain(iter::once(Box::new(Expr::Ident(
|
||||
@ -152,11 +153,9 @@ impl Fold for ExprInjector<'_> {
|
||||
.collect(),
|
||||
})
|
||||
}
|
||||
_ => expr,
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
fn fold_function(&mut self, n: Function) -> Function {
|
||||
n
|
||||
}
|
||||
fn visit_mut_function(&mut self, _: &mut Function) {}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user