diff --git a/.github/workflows/cargo.yml b/.github/workflows/cargo.yml index bbd7ccd969c..3dcb7d2a276 100644 --- a/.github/workflows/cargo.yml +++ b/.github/workflows/cargo.yml @@ -107,7 +107,6 @@ jobs: - swc_ecma_codegen - swc_ecma_codegen_macros - swc_ecma_dep_graph - - swc_ecma_diff - swc_ecma_ext_transforms - swc_ecma_lints - swc_ecma_loader diff --git a/Cargo.lock b/Cargo.lock index 3f4ed43d641..1eba1df9f15 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -620,35 +620,6 @@ dependencies = [ "num_cpus", ] -[[package]] -name = "dbg-swc" -version = "0.10.0" -dependencies = [ - "anyhow", - "pretty_assertions 1.0.0", - "rayon", - "structopt", - "swc_atoms", - "swc_common", - "swc_ecma_ast", - "swc_ecma_codegen", - "swc_ecma_dep_graph", - "swc_ecma_diff", - "swc_ecma_loader", - "swc_ecma_minifier", - "swc_ecma_parser", - "swc_ecma_transforms_base", - "swc_ecma_transforms_react", - "swc_ecma_transforms_typescript", - "swc_ecma_utils", - "swc_ecma_visit", - "swc_node_comments", - "swc_timer", - "tempfile", - "tracing", - "tracing-subscriber", -] - [[package]] name = "debug_unreachable" version = "0.1.1" @@ -1849,18 +1820,6 @@ dependencies = [ "output_vt100", ] -[[package]] -name = "pretty_assertions" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec0cfe1b2403f172ba0f234e500906ee0a3e493fb81092dac23ebefe129301cc" -dependencies = [ - "ansi_term", - "ctor", - "diff", - "output_vt100", -] - [[package]] name = "proc-macro-crate" version = "0.1.5" @@ -2937,7 +2896,7 @@ dependencies = [ name = "swc_ecma_dep_graph" version = "0.58.0" dependencies = [ - "pretty_assertions 0.7.2", + "pretty_assertions", "swc_atoms", "swc_common", "swc_ecma_ast", @@ -2946,22 +2905,6 @@ dependencies = [ "testing", ] -[[package]] -name = "swc_ecma_diff" -version = "0.6.0" -dependencies = [ - "ansi_term", - "auto_impl", - "num-bigint", - "string_cache", - "swc_atoms", - "swc_common", - "swc_ecma_ast", - "swc_ecma_codegen", - "swc_ecma_parser", - "testing", -] - [[package]] name = "swc_ecma_ext_transforms" version = "0.50.0" @@ -3021,7 +2964,7 @@ dependencies = [ "backtrace", "indexmap", "once_cell", - "pretty_assertions 0.7.2", + "pretty_assertions", "rayon", "regex", "retain_mut", @@ -3052,7 +2995,7 @@ dependencies = [ "enum_kind", "lexical", "num-bigint", - "pretty_assertions 0.7.2", + "pretty_assertions", "serde", "serde_json", "smallvec", @@ -3078,7 +3021,7 @@ dependencies = [ "dashmap", "indexmap", "once_cell", - "pretty_assertions 0.7.2", + "pretty_assertions", "semver 1.0.4", "serde", "serde_json", @@ -3100,7 +3043,7 @@ dependencies = [ name = "swc_ecma_transforms" version = "0.114.3" dependencies = [ - "pretty_assertions 0.7.2", + "pretty_assertions", "sourcemap", "swc_atoms", "swc_common", @@ -3408,7 +3351,7 @@ dependencies = [ "ahash", "anyhow", "copyless", - "pretty_assertions 0.7.2", + "pretty_assertions", "rayon", "serde", "serde_json", @@ -3473,7 +3416,7 @@ dependencies = [ "dashmap", "is-macro", "once_cell", - "pretty_assertions 0.7.2", + "pretty_assertions", "regex", "serde", "serde_json", @@ -3661,7 +3604,7 @@ dependencies = [ "ansi_term", "difference", "once_cell", - "pretty_assertions 0.7.2", + "pretty_assertions", "regex", "serde_json", "swc_common", diff --git a/Cargo.toml b/Cargo.toml index 907ffdd365b..2d887db9c37 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,12 +1,10 @@ [workspace] members = [ - "crates/dbg-swc", "crates/jsdoc", "crates/node", "crates/swc_cli", "crates/swc_css", "crates/swc_ecmascript", - "crates/swc_ecma_diff", "crates/swc_ecma_lints", "crates/swc_estree_compat", "crates/swc_plugin", diff --git a/crates/dbg-swc/Cargo.toml b/crates/dbg-swc/Cargo.toml deleted file mode 100644 index 5f86f4624eb..00000000000 --- a/crates/dbg-swc/Cargo.toml +++ /dev/null @@ -1,37 +0,0 @@ -[package] -authors = ["강동윤 "] -description = "Debug tools for swc" -documentation = "https://rustdoc.swc.rs/dbg-swc/" -edition = "2021" -include = ["Cargo.toml", "src/**/*.rs"] -license = "Apache-2.0" -name = "dbg-swc" -repository = "https://github.com/swc-project/swc.git" -version = "0.10.0" - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - -[dependencies] -anyhow = "1" -pretty_assertions = "1.0.0" -rayon = "1" -structopt = "0.3.25" -swc_atoms = {version = "0.2.9", path = "../swc_atoms/"} -swc_common = {version = "0.17.0", path = "../swc_common/", features = ["concurrent"]} -swc_ecma_ast = {version = "0.65.0", path = "../swc_ecma_ast/"} -swc_ecma_codegen = {version = "0.89.0", path = "../swc_ecma_codegen"} -swc_ecma_dep_graph = {version = "0.58.0", path = "../swc_ecma_dep_graph/"} -swc_ecma_diff = {version = "0.6.0", path = "../swc_ecma_diff/"} -swc_ecma_loader = {version = "0.28.0", path = "../swc_ecma_loader/", features = ["lru", "node", "tsc"]} -swc_ecma_minifier = {version = "0.71.0", path = "../swc_ecma_minifier/"} -swc_ecma_parser = {version = "0.87.0", path = "../swc_ecma_parser/"} -swc_ecma_transforms_base = {version = "0.57.0", path = "../swc_ecma_transforms_base/"} -swc_ecma_transforms_react = {version = "0.77.0", path = "../swc_ecma_transforms_react/"} -swc_ecma_transforms_typescript = {version = "0.79.0", path = "../swc_ecma_transforms_typescript/"} -swc_ecma_utils = {version = "0.64.0", path = "../swc_ecma_utils/"} -swc_ecma_visit = {version = "0.51.0", path = "../swc_ecma_visit/"} -swc_node_comments = {version = "0.4.0", path = "../swc_node_comments/"} -swc_timer = {version = "0.4.0", path = "../swc_timer/"} -tempfile = "3.2.0" -tracing = "0.1.29" -tracing-subscriber = {version = "0.3.5", features = ["env-filter"]} diff --git a/crates/dbg-swc/README.md b/crates/dbg-swc/README.md deleted file mode 100644 index f96b4a7f91a..00000000000 --- a/crates/dbg-swc/README.md +++ /dev/null @@ -1,13 +0,0 @@ -# dbg-swc - -## `dbg-swc reduce-min` - -``` -dbg-swc reduce-min --build '' --test 'npm test.spec' --working-dir ~/src/ionic-framework/packages/react/ ~/src/ionic-framework/packages/react/src/index.ts -``` - -(TODO) e.g. next.js app - -```sh -dbg-swc reduce-min --build 'rm -rf .next && npx next build' --test 'dbg-swc grab-console http://localhost:3000 --script test.js --start "npm start"' ~/your/next/app/pages/index.js ~/your/next/app/pages/index.js -``` diff --git a/crates/dbg-swc/scripts/install.sh b/crates/dbg-swc/scripts/install.sh deleted file mode 100755 index a829846f428..00000000000 --- a/crates/dbg-swc/scripts/install.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/usr/bin/env bash -set -eu - -cargo install --locked --debug --path . \ No newline at end of file diff --git a/crates/dbg-swc/scripts/tesh.sh b/crates/dbg-swc/scripts/tesh.sh deleted file mode 100755 index 7f7ed105731..00000000000 --- a/crates/dbg-swc/scripts/tesh.sh +++ /dev/null @@ -1,5 +0,0 @@ -#!/usr/bin/env bash -set -eu - - -cargo run -- $@ \ No newline at end of file diff --git a/crates/dbg-swc/scripts/try-next.sh b/crates/dbg-swc/scripts/try-next.sh deleted file mode 100755 index e213dd3adf1..00000000000 --- a/crates/dbg-swc/scripts/try-next.sh +++ /dev/null @@ -1,6 +0,0 @@ -#!/usr/bin/env bash -set -eu - -./scripts/install.sh - -dbg-swc reduce-min --build 'rm -rf .next && npx next build' --test 'dbg-swc grab-console http://localhost:3000 --script test.js --start "npm start"' $@ \ No newline at end of file diff --git a/crates/dbg-swc/src/main.rs b/crates/dbg-swc/src/main.rs deleted file mode 100644 index 6ed96277c61..00000000000 --- a/crates/dbg-swc/src/main.rs +++ /dev/null @@ -1,71 +0,0 @@ -use self::{minified::DiffMinifiedCommand, reduce_min::ReduceMinCommand}; -use anyhow::Result; -use std::{env, io::stderr, str::FromStr, sync::Arc, time::Instant}; -use structopt::StructOpt; -use swc_common::{ - errors::{Handler, HANDLER}, - SourceMap, GLOBALS, -}; -use tracing_subscriber::EnvFilter; - -mod minified; -mod reduce_min; -mod util; - -#[derive(Debug, StructOpt)] -enum Cmd { - DiffMin(DiffMinifiedCommand), - ReduceMin(ReduceMinCommand), -} - -struct Track { - start: Instant, -} - -impl Drop for Track { - fn drop(&mut self) { - eprintln!("Done in {:?}", self.start.elapsed()); - } -} - -fn main() -> Result<()> { - let globals = swc_common::Globals::default(); - let cm = Arc::new(SourceMap::default()); - let handler = Handler::with_emitter_writer(Box::new(stderr()), Some(cm.clone())); - - let _logger = { - let log_env = env::var("RUST_LOG").unwrap_or_else(|_| "info".to_string()); - - let logger = tracing_subscriber::FmtSubscriber::builder() - .without_time() - .with_target(false) - .with_ansi(true) - .with_env_filter(EnvFilter::from_str(&log_env).unwrap()) - .with_test_writer() - .pretty() - .finish(); - - tracing::subscriber::set_global_default(logger) - }; - - let _track = Track { - start: Instant::now(), - }; - - let cmd = Cmd::from_args(); - - GLOBALS.set(&globals, || { - HANDLER.set(&handler, || { - match cmd { - Cmd::DiffMin(cmd) => { - cmd.run(cm.clone())?; - } - Cmd::ReduceMin(cmd) => { - cmd.run(cm.clone())?; - } - } - - Ok(()) - }) - }) -} diff --git a/crates/dbg-swc/src/minified.rs b/crates/dbg-swc/src/minified.rs deleted file mode 100644 index f0666f6cf19..00000000000 --- a/crates/dbg-swc/src/minified.rs +++ /dev/null @@ -1,192 +0,0 @@ -use crate::util::{parse, print_js}; -use anyhow::{bail, Context, Result}; -use std::{ - io::Write, - path::PathBuf, - process::{Command, Stdio}, - sync::Arc, -}; -use structopt::StructOpt; -use swc_common::{util::take::Take, FileName, Mark, SourceMap}; -use swc_ecma_ast::*; -use swc_ecma_diff::Diff; -use swc_ecma_minifier::option::{ExtraOptions, MinifyOptions}; -use swc_ecma_transforms_base::{fixer::fixer, resolver::resolver_with_mark}; -use swc_ecma_visit::{VisitMut, VisitMutWith}; -use tempfile::NamedTempFile; - -/// Diff the output of swc minifier and terser. -#[derive(Debug, StructOpt)] -pub(crate) struct DiffMinifiedCommand { - input: PathBuf, - - #[structopt(long)] - no_mangle: bool, -} - -impl DiffMinifiedCommand { - pub fn run(self, cm: Arc) -> Result<()> { - let terser_output = self - .get_output_from_terser() - .context("failed to get output from terser")?; - - let fm = cm - .load_file(&self.input) - .context("failed to load input file")?; - - let top_level_mark = Mark::fresh(Mark::root()); - - let mut swc_module = { - let mut m = parse(&fm).context("failed to parse input file using swc")?; - - m.visit_mut_with(&mut resolver_with_mark(top_level_mark)); - m.visit_mut_with(&mut fixer(None)); - m.visit_mut_with(&mut Normalizer::default()); - - m = swc_ecma_minifier::optimize( - m, - cm.clone(), - None, - None, - &MinifyOptions { - compress: Some(Default::default()), - mangle: if self.no_mangle { - None - } else { - Some(Default::default()) - }, - ..Default::default() - }, - &ExtraOptions { top_level_mark }, - ); - - m.visit_mut_with(&mut fixer(None)); - m.visit_mut_with(&mut Normalizer::default()); - m.visit_mut_with(&mut BeforeDiffNormalizer::default()); - - m - }; - - let terser_fm = cm.new_source_file(FileName::Anon, terser_output); - let mut terser_module = parse(&terser_fm)?; - - { - terser_module.visit_mut_with(&mut resolver_with_mark(top_level_mark)); - terser_module.visit_mut_with(&mut fixer(None)); - terser_module.visit_mut_with(&mut Normalizer::default()); - terser_module.visit_mut_with(&mut BeforeDiffNormalizer::default()); - } - { - // Diff - - let config = swc_ecma_diff::Config { ignore_span: true }; - let mut ctx = swc_ecma_diff::Ctx::new(config); - let diff_res = swc_module.diff(&mut terser_module, &mut ctx); - - eprintln!("Diff: \n{}", diff_res); - } - - swc_module.visit_mut_with(&mut Normalizer::default()); - terser_module.visit_mut_with(&mut Normalizer::default()); - - let swc_output = print_js(cm.clone(), &swc_module, None).context("failed to print js")?; - let terser_output = print_js(cm, &terser_module, None).context("failed to print js")?; - - if swc_output == terser_output { - return Ok(()); - } - - let mut swc_file = NamedTempFile::new()?; - - writeln!(swc_file, "{}", swc_output)?; - - let mut terser_file = NamedTempFile::new()?; - - writeln!(terser_file, "{}", terser_output)?; - - Command::new("code") - .arg("--wait") - .arg("--diff") - .arg(&swc_file.path()) - .arg(&terser_file.path()) - .status()?; - - Ok(()) - } - - /// Invoke `terser` - fn get_output_from_terser(&self) -> Result { - let mut c = Command::new("terser"); - - c.arg("--compress"); - - if !self.no_mangle { - c.arg("--mangle"); - } - - let output = c - .arg("--") - .arg(&self.input) - .stderr(Stdio::inherit()) - .output() - .context("failed to run terser")?; - - if !output.status.success() { - bail!("terser failed with status code {}", output.status); - } - - let src = String::from_utf8(output.stdout).context("failed to parse terser output")?; - Ok(src) - } -} - -#[derive(Debug, Default)] -struct Normalizer {} - -impl VisitMut for Normalizer { - fn visit_mut_new_expr(&mut self, e: &mut NewExpr) { - e.visit_mut_children_with(self); - - if let Some(args) = &e.args { - if args.is_empty() { - e.args = None; - } - } - } - - fn visit_mut_stmt(&mut self, s: &mut Stmt) { - s.visit_mut_children_with(self); - - if let Stmt::Decl(Decl::Var(v)) = s { - if v.decls.is_empty() { - s.take(); - } - } - } - - fn visit_mut_stmts(&mut self, stmts: &mut Vec) { - stmts.visit_mut_children_with(self); - - stmts.retain(|s| !matches!(s, Stmt::Empty(..))); - } -} - -#[derive(Debug, Default)] -struct BeforeDiffNormalizer {} - -impl VisitMut for BeforeDiffNormalizer { - fn visit_mut_stmt(&mut self, s: &mut Stmt) { - s.visit_mut_children_with(self); - - if let Stmt::Block(bs) = s { - if bs.stmts.len() == 1 { - *s = bs.stmts[0].take(); - } - } - } - - fn visit_mut_str(&mut self, s: &mut Str) { - s.visit_mut_children_with(self); - s.has_escape = false; - } -} diff --git a/crates/dbg-swc/src/reduce_min/deps.rs b/crates/dbg-swc/src/reduce_min/deps.rs deleted file mode 100644 index 520541fd728..00000000000 --- a/crates/dbg-swc/src/reduce_min/deps.rs +++ /dev/null @@ -1,131 +0,0 @@ -use crate::util::parse; -use anyhow::{Context, Result}; -use rayon::prelude::*; -use std::{ - path::{Path, PathBuf}, - sync::{Arc, Mutex}, -}; -use swc_common::{ - collections::AHashMap, comments::NoopComments, errors::HANDLER, FileName, SourceFile, - SourceMap, GLOBALS, -}; -use swc_ecma_loader::{resolve::Resolve, resolvers::node::NodeModulesResolver, TargetEnv}; -use tracing::info; - -pub fn collect_deps(cm: Arc, working_dir: &Path, entry: &Path) -> Result> { - let collector = DependencyCollector { - cm, - working_dir: working_dir.to_path_buf(), - cache: Default::default(), - resolver: Box::new(NodeModulesResolver::new( - TargetEnv::Node, - Default::default(), - false, - )), - }; - - collector.load_recursively(Arc::new(FileName::Real(entry.to_path_buf())))?; - - let files = collector.cache.into_inner()?; - - Ok(files - .into_iter() - .map(|(_, file)| file.fm.name.clone()) - .filter_map(|f| match f { - FileName::Real(v) => Some(v), - _ => None, - }) - .collect()) -} - -struct DependencyCollector { - cm: Arc, - - #[allow(unused)] - working_dir: PathBuf, - - cache: Mutex, Arc>>, - - resolver: Box, -} - -impl DependencyCollector { - fn load_recursively(&self, name: Arc) -> Result<()> { - if self.cache.lock().unwrap().contains_key(&name) { - return Ok(()); - } - - info!("Loading {}", name); - - let fm = match &*name { - FileName::Real(path) => self.cm.load_file(path)?, - FileName::Custom(..) => return Ok(()), - _ => { - todo!("load({:?})", name) - } - }; - - self.cache - .lock() - .unwrap() - .insert(name.clone(), Arc::new(ModuleData { fm: fm.clone() })); - - if let FileName::Real(name) = &*name { - if let Some(ext) = name.extension() { - if ext == "json" { - return Ok(()); - } - } - } - - let module = parse(&fm)?; - - let deps = swc_ecma_dep_graph::analyze_dependencies(&module, &NoopComments); - let deps = deps - .into_iter() - .filter(|dep| &*dep.specifier != "next") - .collect::>(); - - let _res = GLOBALS.with(|globals| { - HANDLER.with(|handler| { - deps.into_par_iter() - .map(|dep| { - GLOBALS.set(globals, || { - HANDLER.set(handler, || { - let res = self - .resolver - .resolve(&fm.name, &dep.specifier) - .with_context(|| { - format!( - "failed to resolve `{}` from `{}`", - dep.specifier, fm.name - ) - })?; - - Ok((res, dep)) - }) - }) - }) - .map(|res| { - GLOBALS.set(globals, || { - HANDLER.set(handler, || { - res.and_then(|(name, dep)| { - let name = Arc::new(name); - self.load_recursively(name.clone()).with_context(|| { - format!("failed to load `{}` (`{}`)", name, dep.specifier) - }) - }) - }) - }) - }) - .collect::>() - }) - })?; - - Ok(()) - } -} - -struct ModuleData { - fm: Arc, -} diff --git a/crates/dbg-swc/src/reduce_min/mod.rs b/crates/dbg-swc/src/reduce_min/mod.rs deleted file mode 100644 index d484f2bcd7a..00000000000 --- a/crates/dbg-swc/src/reduce_min/mod.rs +++ /dev/null @@ -1,241 +0,0 @@ -use self::{deps::collect_deps, types::ignore_typescript}; -use crate::util::{parse, print_js}; -use anyhow::{bail, Context, Result}; -use std::{ - path::PathBuf, - process::{Command, Stdio}, - sync::Arc, -}; -use structopt::StructOpt; -use swc_common::{comments::NoopComments, Mark, SourceMap}; -use swc_ecma_minifier::option::{ExtraOptions, MinifyOptions}; -use swc_ecma_transforms_base::{ - fixer::fixer, - helpers::{inject_helpers, Helpers, HELPERS}, - hygiene::hygiene, - resolver::resolver_with_mark, -}; -use swc_ecma_transforms_typescript::strip_with_jsx; -use swc_ecma_visit::{FoldWith, VisitMutWith}; -use swc_node_comments::SwcComments; -use swc_timer::timer; -use tracing::{info, span, Level}; - -mod deps; -mod types; - -/// This tool repeat replacing one file with a minified form at a time. -#[derive(Debug, StructOpt)] -pub(crate) struct ReduceMinCommand { - entry: PathBuf, - - #[structopt(long)] - working_dir: PathBuf, - - /// This command is invoked using `bash`. - #[structopt(long = "build")] - build_command: String, - - /// This command is invoked using `bash`. - #[structopt(long = "test")] - test_command: String, -} - -impl ReduceMinCommand { - pub(crate) fn run(self, cm: Arc) -> Result<()> { - let all_files = { - let _timer = timer!("collect list of files to patch"); - collect_deps(cm.clone(), &self.working_dir, &self.entry)? - }; - - let mut runner = Runner { - cm, - comments: Default::default(), - working_dir: self.working_dir, - build_command: self.build_command, - test_command: self.test_command, - expected: Default::default(), - }; - - { - let _span = span!(Level::ERROR, "initial run, without minification").entered(); - runner.expected = runner.check().context("initial check failed")?; - } - - runner.run(all_files) - } -} - -struct Runner { - cm: Arc, - - comments: SwcComments, - - working_dir: PathBuf, - build_command: String, - test_command: String, - - expected: String, -} - -/// Restores original content on drop -struct Patch { - path: PathBuf, - orig: Arc, -} - -impl Drop for Patch { - fn drop(&mut self) { - let _ = std::fs::write(&self.path, self.orig.as_bytes()); - } -} - -impl Runner { - fn patch_file(&mut self, path: PathBuf) -> Result<(Patch, String)> { - (|| -> Result<_> { - let fm = self.cm.load_file(&path).context("failed to load file")?; - - let top_level_mark = Mark::fresh(Mark::root()); - - let mut m = parse(&fm).context("failed to parse input file using swc")?; - - let helpers = Helpers::new(false); - - m = HELPERS.set(&helpers, || { - let mut m = m; - m.visit_mut_with(&mut resolver_with_mark(top_level_mark)); - m.visit_mut_with(&mut strip_with_jsx( - self.cm.clone(), - swc_ecma_transforms_typescript::Config { - ..Default::default() - }, - NoopComments, - top_level_mark, - )); - m = m.fold_with(&mut swc_ecma_transforms_react::react( - self.cm.clone(), - None::, - Default::default(), - top_level_mark, - )); - - m = swc_ecma_minifier::optimize( - m, - self.cm.clone(), - None, - None, - &MinifyOptions { - compress: Some(Default::default()), - mangle: None, - ..Default::default() - }, - &ExtraOptions { top_level_mark }, - ); - - m.visit_mut_with(&mut inject_helpers()); - - m.visit_mut_with(&mut hygiene()); - m.visit_mut_with(&mut fixer(None)); - - if let Some(ext) = path.extension() { - if ext == "tsx" || ext == "ts" { - m.visit_mut_with(&mut ignore_typescript(self.comments.clone())); - } - } - - m - }); - - let mut patched = print_js(self.cm.clone(), &m, Some(&self.comments))?; - - // Ignore helpers injected by swc - macro_rules! ignore { - ($s:expr) => {{ - patched = patched.replace($s, concat!("//@ts-ignore\n", $s)); - }}; - } - - // TODO: Find better way - ignore!("function _"); - ignore!("_extends = "); - ignore!("return _extends.apply(this, arguments)"); - - std::fs::write(&path, patched.as_bytes()).context("failed to write patched content")?; - - let patch = Patch { - path: path.clone(), - orig: fm.src.clone(), - }; - - Ok((patch, patched)) - })() - .with_context(|| format!("failed to patch file: {}", path.display())) - } - - fn run(mut self, files: Vec) -> Result<()> { - // Patch one file at a time. - for file in files { - if let Some(ext) = file.extension() { - if ext == "json" { - info!("Skipping json file"); - continue; - } - } - - let _span = span!(Level::ERROR, "patch", file = &*file.display().to_string()).entered(); - - let (_patch, patched) = self.patch_file(file.clone())?; - - let actual = self.check().with_context(|| { - format!( - "test failed for `{}`\nPatched:\n{}", - file.display(), - patched - ) - })?; - - if actual != self.expected { - bail!("expected: {}, actual: {}", self.expected, actual); - } - } - - Ok(()) - } - - /// Build, test, and grab the console output. - fn check(&mut self) -> Result { - { - info!("Building app"); - - let mut cmd = Command::new("bash"); - let status = cmd - .current_dir(&self.working_dir) - .arg("-c") - .arg(&self.build_command) - .status() - .context("failed to run build command")?; - - if !status.success() { - bail!("build failed"); - } - } - - info!("Testing app"); - - let mut cmd = Command::new("bash"); - - let output = cmd - .current_dir(&self.working_dir) - .arg("-c") - .arg(&self.test_command) - .stderr(Stdio::inherit()) - .output() - .context("failed to get test output")?; - - if !output.status.success() { - bail!("test failed"); - } - - Ok(String::from_utf8_lossy(&output.stdout).to_string()) - } -} diff --git a/crates/dbg-swc/src/reduce_min/types.rs b/crates/dbg-swc/src/reduce_min/types.rs deleted file mode 100644 index fb1f2b0c43d..00000000000 --- a/crates/dbg-swc/src/reduce_min/types.rs +++ /dev/null @@ -1,88 +0,0 @@ -use swc_common::{ - comments::{Comment, CommentKind, Comments}, - Spanned, DUMMY_SP, -}; -use swc_ecma_ast::*; -use swc_ecma_visit::{VisitMut, VisitMutWith}; -use swc_node_comments::SwcComments; - -/// Add `@ts-ignore` to all statements. -pub fn ignore_typescript(comments: SwcComments) -> impl VisitMut { - AddTypes { - comments, - should_not_annotate_type: Default::default(), - } -} - -struct AddTypes { - comments: SwcComments, - - should_not_annotate_type: bool, -} - -impl VisitMut for AddTypes { - /// - /// - `(this.foo)` => `(this as any).foo` - fn visit_mut_member_expr(&mut self, e: &mut MemberExpr) { - e.visit_mut_children_with(self); - - if let Expr::This(..) = &*e.obj { - e.obj = Expr::Paren(ParenExpr { - span: DUMMY_SP, - expr: Box::new(Expr::TsAs(TsAsExpr { - span: DUMMY_SP, - expr: e.obj.clone(), - type_ann: any_type(), - })), - }) - .into(); - } - } - - fn visit_mut_stmt(&mut self, s: &mut Stmt) { - s.visit_mut_children_with(self); - - self.comments.add_leading( - s.span().lo, - Comment { - kind: CommentKind::Line, - span: DUMMY_SP, - text: "@ts-ignore".into(), - }, - ); - } - - fn visit_mut_var_decl_or_expr(&mut self, n: &mut VarDeclOrExpr) { - let old = self.should_not_annotate_type; - self.should_not_annotate_type = true; - n.visit_mut_children_with(self); - self.should_not_annotate_type = old; - } - - fn visit_mut_var_decl_or_pat(&mut self, n: &mut VarDeclOrPat) { - let old = self.should_not_annotate_type; - self.should_not_annotate_type = true; - n.visit_mut_children_with(self); - self.should_not_annotate_type = old; - } - - fn visit_mut_var_declarator(&mut self, v: &mut VarDeclarator) { - v.visit_mut_children_with(self); - - if !self.should_not_annotate_type { - if let Pat::Ident(id) = &mut v.name { - id.type_ann = Some(TsTypeAnn { - span: DUMMY_SP, - type_ann: any_type(), - }); - } - } - } -} - -fn any_type() -> Box { - Box::new(TsType::TsKeywordType(TsKeywordType { - span: DUMMY_SP, - kind: TsKeywordTypeKind::TsAnyKeyword, - })) -} diff --git a/crates/dbg-swc/src/util.rs b/crates/dbg-swc/src/util.rs deleted file mode 100644 index 5bbbfb95df5..00000000000 --- a/crates/dbg-swc/src/util.rs +++ /dev/null @@ -1,70 +0,0 @@ -use anyhow::{anyhow, Result}; -use std::sync::Arc; -use swc_common::{comments::Comments, input::SourceFileInput, FileName, SourceFile, SourceMap}; -use swc_ecma_ast::{EsVersion, Module}; -use swc_ecma_parser::{lexer::Lexer, EsConfig, Parser, Syntax, TsConfig}; -use swc_ecma_utils::HANDLER; - -pub(crate) fn parse(fm: &SourceFile) -> Result { - let syntax = Syntax::Es(EsConfig { - jsx: true, - ..Default::default() - }); - - let syntax = match &fm.name { - FileName::Real(p) => match p.extension() { - Some(ext) => { - if ext == "tsx" { - Syntax::Typescript(TsConfig { - tsx: true, - decorators: true, - ..Default::default() - }) - } else if ext == "ts" { - Syntax::Typescript(TsConfig { - decorators: true, - ..Default::default() - }) - } else { - syntax - } - } - None => syntax, - }, - _ => syntax, - }; - - let lexer = Lexer::new(syntax, EsVersion::latest(), SourceFileInput::from(fm), None); - - let mut parser = Parser::new_from(lexer); - - parser.parse_module().map_err(|err| { - HANDLER.with(|handler| { - err.into_diagnostic(handler).emit(); - }); - - anyhow!("failed to parse module") - }) -} - -pub(crate) fn print_js( - cm: Arc, - m: &Module, - comments: Option<&dyn Comments>, -) -> Result { - let mut buf = vec![]; - - { - let wr = swc_ecma_codegen::text_writer::JsWriter::new(cm.clone(), "\n", &mut buf, None); - let mut emitter = swc_ecma_codegen::Emitter { - cfg: swc_ecma_codegen::Config { minify: false }, - cm, - comments, - wr, - }; - - emitter.emit_module(m)?; - } - - Ok(String::from_utf8(buf)?) -} diff --git a/crates/swc_ecma_diff/Cargo.toml b/crates/swc_ecma_diff/Cargo.toml deleted file mode 100644 index 3c1cf6d2203..00000000000 --- a/crates/swc_ecma_diff/Cargo.toml +++ /dev/null @@ -1,28 +0,0 @@ -[package] -authors = ["강동윤 "] -description = "Diffing tools for ECMAScript" -documentation = "https://rustdoc.swc.rs/swc_ecma_diff/" -edition = "2021" -include = ["Cargo.toml", "src/**/*.rs"] -license = "Apache-2.0" -name = "swc_ecma_diff" -repository = "https://github.com/swc-project/swc.git" -version = "0.6.0" - -[package.metadata.docs.rs] -all-features = true -rustdoc-args = ["--cfg", "docsrs"] - -[dependencies] -ansi_term = "0.12.1" -auto_impl = "0.5.0" -num-bigint = "0.2" -string_cache = "0.8" -swc_atoms = {version = "0.2.9", path = "../swc_atoms"} -swc_common = {version = "0.17.0", path = "../swc_common"} -swc_ecma_ast = {version = "0.65.0", path = "../swc_ecma_ast"} - -[dev-dependencies] -swc_ecma_codegen = {version = "0.89.0", path = "../swc_ecma_codegen"} -swc_ecma_parser = {version = "0.87.0", path = "../swc_ecma_parser"} -testing = {version = "0.18.0", path = "../testing"} diff --git a/crates/swc_ecma_diff/src/ctx.rs b/crates/swc_ecma_diff/src/ctx.rs deleted file mode 100644 index ed81d3ac787..00000000000 --- a/crates/swc_ecma_diff/src/ctx.rs +++ /dev/null @@ -1,72 +0,0 @@ -use crate::{Config, Diff, DiffResult}; -use swc_atoms::JsWord; - -/// The context for [Diff]. This contains config and path. -/// -/// This is very inefficient, but it's fine as this will be used only for -/// debugging tools. I don't want to bother with lifetimes. -#[derive(Debug, Clone)] -pub struct Ctx { - pub(crate) path: Vec, - pub(crate) config: Config, -} - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub enum PathComponent { - StructProp { struct_name: JsWord, key: JsWord }, - VecElem { l: usize, r: usize }, -} - -impl Ctx { - pub fn new(config: Config) -> Self { - Ctx { - path: Default::default(), - config, - } - } - - pub(crate) fn diff_struct(&mut self, struct_name: &str, f: F) -> DiffResult - where - F: FnOnce(&mut StructDiffCtx), - { - let mut helper = StructDiffCtx { - parent: self, - results: Default::default(), - struct_name: struct_name.into(), - }; - f(&mut helper); - - if helper.results.is_empty() { - return DiffResult::Identical; - } - - DiffResult::Multiple(helper.results) - } -} - -pub(crate) struct StructDiffCtx<'a> { - parent: &'a mut Ctx, - results: Vec, - struct_name: JsWord, -} - -impl StructDiffCtx<'_> { - pub fn field(&mut self, field_name: &str, l: &mut T, r: &mut T) - where - T: Diff, - { - let mut ctx = self.parent.clone(); - ctx.path.push(PathComponent::StructProp { - struct_name: self.struct_name.clone(), - key: field_name.into(), - }); - - let diff = l.diff(r, &mut ctx); - - if matches!(diff, DiffResult::Identical) { - return; - } - - self.results.push(diff); - } -} diff --git a/crates/swc_ecma_diff/src/js_ast/expr.rs b/crates/swc_ecma_diff/src/js_ast/expr.rs deleted file mode 100644 index f9125d9552b..00000000000 --- a/crates/swc_ecma_diff/src/js_ast/expr.rs +++ /dev/null @@ -1,166 +0,0 @@ -use crate::{Ctx, Diff, DiffResult, Node}; -use swc_common::EqIgnoreSpan; -use swc_ecma_ast::*; - -diff_enum!( - Expr, - [ - This, - Array, - Object, - Fn, - Unary, - Update, - Bin, - Assign, - Member, - SuperProp, - Cond, - Call, - New, - Seq, - Ident, - Lit, - Tpl, - TaggedTpl, - Arrow, - Class, - Yield, - MetaProp, - Await, - Paren, - JSXMember, - JSXNamespacedName, - JSXEmpty, - JSXElement, - JSXFragment, - TsTypeAssertion, - TsConstAssertion, - TsNonNull, - TsAs, - PrivateName, - OptChain, - Invalid - ] -); - -diff_enum!(PropOrSpread, [Prop, Spread]); -diff_enum!(BlockStmtOrExpr, [BlockStmt, Expr]); -diff_enum!(SuperProp, [Computed, Ident]); -diff_enum!(Callee, [Expr, Super, Import]); -diff_enum!(Lit, [Str, Bool, Null, BigInt, Num, Regex, JSXText]); -diff_enum!(JSXAttrOrSpread, [JSXAttr, SpreadElement]); -diff_enum!(Prop, [Shorthand, KeyValue, Assign, Getter, Setter, Method]); - -diff_string_enum!(MetaPropKind); - -diff_struct!(ThisExpr, [span]); -diff_struct!(ArrayLit, [span, elems]); -diff_struct!(ExprOrSpread, [spread, expr]); -diff_struct!(ObjectLit, [span, props]); -diff_struct!(FnExpr, [ident, function]); -diff_struct!(UnaryExpr, [span, op, arg]); -diff_struct!(Decorator, [span, expr]); -diff_struct!(UpdateExpr, [span, prefix, op, arg]); -diff_struct!(BinExpr, [span, op, left, right]); -diff_struct!(AssignExpr, [span, op, left, right]); -diff_struct!(MemberExpr, [span, obj, prop]); -diff_struct!(SuperPropExpr, [span, obj, prop]); -diff_enum!(MemberProp, [Ident, PrivateName, Computed]); -diff_struct!(CondExpr, [span, test, cons, alt]); -diff_struct!(CallExpr, [span, callee, args, type_args]); -diff_struct!(NewExpr, [span, callee, args, type_args]); -diff_struct!(SeqExpr, [span, exprs]); -diff_struct!(TaggedTpl, [span, tag, tpl, type_params]); -diff_struct!(TplElement, [span, cooked, raw, tail]); -diff_struct!(Str, [span, value, has_escape, kind]); -diff_struct!( - ArrowExpr, - [ - span, - params, - body, - is_async, - is_generator, - type_params, - return_type - ] -); -diff_struct!(ClassExpr, [ident, class]); -diff_struct!(YieldExpr, [span, arg, delegate]); -diff_struct!(MetaPropExpr, [span, kind]); -diff_struct!(AwaitExpr, [span, arg]); -diff_struct!(ParenExpr, [span, expr]); -diff_struct!(JSXMemberExpr, [obj, prop]); -diff_struct!(JSXNamespacedName, [ns, name]); -diff_enum!(JSXObject, [JSXMemberExpr, Ident]); -diff_struct!(JSXEmptyExpr, [span]); -diff_struct!(JSXElement, [span, opening, children, closing]); -diff_struct!( - JSXOpeningElement, - [span, name, attrs, self_closing, type_args] -); -diff_enum!( - JSXElementChild, - [ - JSXElement, - JSXText, - JSXSpreadChild, - JSXExprContainer, - JSXFragment - ] -); -diff_struct!(JSXAttr, [span, name, value]); -diff_enum!(JSXAttrName, [Ident, JSXNamespacedName]); -diff_enum!( - JSXAttrValue, - [Lit, JSXExprContainer, JSXElement, JSXFragment] -); -diff_struct!(JSXClosingElement, [span, name]); -diff_struct!(JSXFragment, [span, opening, children, closing]); -diff_enum!(JSXElementName, [Ident, JSXMemberExpr, JSXNamespacedName]); -diff_struct!(JSXOpeningFragment, [span]); -diff_struct!(JSXClosingFragment, [span]); -diff_struct!(JSXSpreadChild, [span, expr]); -diff_struct!(JSXExprContainer, [span, expr]); -diff_enum!(JSXExpr, [JSXEmptyExpr, Expr]); -diff_struct!(PrivateName, [span, id]); -diff_struct!(OptChainExpr, [span, question_dot_token, expr]); -diff_struct!(SpreadElement, [dot3_token, expr]); -diff_struct!(Super, [span]); -diff_struct!(Import, [span]); -diff_struct!(Bool, [span, value]); -diff_struct!(Null, [span]); -diff_struct!(Number, [span, value]); -diff_struct!(BigInt, [span, value]); -diff_struct!(Regex, [span, exp, flags]); -diff_struct!(JSXText, [span, value, raw]); -diff_struct!(AssignProp, [key, value]); -diff_struct!(KeyValueProp, [key, value]); -diff_struct!(GetterProp, [span, key, type_ann, body]); -diff_struct!(SetterProp, [span, key, param, body]); -diff_struct!(MethodProp, [key, function]); -diff_enum!(PropName, [Ident, Str, BigInt, Num, Computed]); -diff_struct!(ComputedPropName, [span, expr]); -diff_struct!(BindingIdent, [id, type_ann]); - -/// Ignored -impl Diff for StrKind { - fn diff(&mut self, _: &mut Self, _: &mut Ctx) -> DiffResult { - DiffResult::Identical - } -} - -impl Diff for Tpl { - fn diff(&mut self, other: &mut Self, ctx: &mut Ctx) -> DiffResult { - if self.eq_ignore_span(&*other) { - return crate::DiffResult::Identical; - } - - DiffResult::Different(crate::Difference { - path: ctx.path.clone(), - left: Node(format!("{:?}", self)), - right: Node(format!("{:?}", other)), - }) - } -} diff --git a/crates/swc_ecma_diff/src/js_ast/ident.rs b/crates/swc_ecma_diff/src/js_ast/ident.rs deleted file mode 100644 index 2aac616c461..00000000000 --- a/crates/swc_ecma_diff/src/js_ast/ident.rs +++ /dev/null @@ -1,5 +0,0 @@ -use swc_ecma_ast::*; - -// TODO: Allow renaming of identifiers. - -diff_struct!(Ident, [span, sym, optional]); diff --git a/crates/swc_ecma_diff/src/js_ast/mod.rs b/crates/swc_ecma_diff/src/js_ast/mod.rs deleted file mode 100644 index fe45d700185..00000000000 --- a/crates/swc_ecma_diff/src/js_ast/mod.rs +++ /dev/null @@ -1,15 +0,0 @@ -//! Implementation of [crate::Diff] for types in [swc_ecma_ast]. - -use swc_ecma_ast::*; - -mod expr; -mod ident; -mod ops; -mod pat; -mod stmt; -mod typescript; - -diff_struct!(Module, [span, body, shebang]); -diff_struct!(Invalid, [span]); - -diff_enum!(ModuleItem, [Stmt, ModuleDecl]); diff --git a/crates/swc_ecma_diff/src/js_ast/ops.rs b/crates/swc_ecma_diff/src/js_ast/ops.rs deleted file mode 100644 index 2cf119e7ead..00000000000 --- a/crates/swc_ecma_diff/src/js_ast/ops.rs +++ /dev/null @@ -1,9 +0,0 @@ -use swc_ecma_ast::*; - -diff_string_enum!(AssignOp); -diff_string_enum!(UnaryOp); -diff_string_enum!(UpdateOp); -diff_string_enum!(VarDeclKind); -diff_string_enum!(BinaryOp); -trivial!(MethodKind); -trivial!(TsTypeOperatorOp); diff --git a/crates/swc_ecma_diff/src/js_ast/pat.rs b/crates/swc_ecma_diff/src/js_ast/pat.rs deleted file mode 100644 index 596fb6f4de0..00000000000 --- a/crates/swc_ecma_diff/src/js_ast/pat.rs +++ /dev/null @@ -1,12 +0,0 @@ -use swc_ecma_ast::*; - -diff_enum!(Pat, [Ident, Rest, Array, Object, Invalid, Assign, Expr]); -diff_enum!(PatOrExpr, [Pat, Expr]); -diff_struct!(ArrayPat, [span, elems, optional, type_ann]); -diff_struct!(ObjectPat, [span, props, optional, type_ann]); -diff_struct!(RestPat, [span, dot3_token, arg, type_ann]); -diff_struct!(AssignPat, [span, left, right, type_ann]); - -diff_enum!(ObjectPatProp, [KeyValue, Assign, Rest]); -diff_struct!(KeyValuePatProp, [key, value]); -diff_struct!(AssignPatProp, [span, key, value]); diff --git a/crates/swc_ecma_diff/src/js_ast/stmt.rs b/crates/swc_ecma_diff/src/js_ast/stmt.rs deleted file mode 100644 index 91e172d2990..00000000000 --- a/crates/swc_ecma_diff/src/js_ast/stmt.rs +++ /dev/null @@ -1,188 +0,0 @@ -use swc_ecma_ast::*; - -diff_enum!( - Stmt, - [ - Block, Empty, Debugger, With, Return, Labeled, Break, Continue, If, Switch, Throw, Try, - While, DoWhile, For, ForIn, ForOf, Decl, Expr - ] -); - -diff_struct!(BlockStmt, [span, stmts]); -diff_struct!(EmptyStmt, [span]); -diff_struct!(DebuggerStmt, [span]); -diff_struct!(WithStmt, [span, obj, body]); -diff_struct!(ReturnStmt, [span, arg]); -diff_struct!(ThrowStmt, [span, arg]); -diff_struct!(LabeledStmt, [span, label, body]); -diff_struct!(BreakStmt, [span, label]); -diff_struct!(ContinueStmt, [span, label]); -diff_struct!(IfStmt, [span, test, cons, alt]); -diff_struct!(SwitchStmt, [span, discriminant, cases]); -diff_struct!(SwitchCase, [span, test, cons]); -diff_struct!(TryStmt, [span, block, handler, finalizer]); -diff_struct!(WhileStmt, [span, test, body]); -diff_struct!(DoWhileStmt, [span, test, body]); -diff_struct!(ForStmt, [span, init, test, update, body]); -diff_struct!(ForInStmt, [span, left, right, body]); -diff_struct!(ForOfStmt, [span, left, right, body, await_token]); -diff_struct!(ExprStmt, [span, expr]); - -diff_struct!(CatchClause, [span, param, body]); - -diff_enum!(VarDeclOrPat, [VarDecl, Pat]); -diff_enum!(VarDeclOrExpr, [VarDecl, Expr]); - -diff_enum!( - Decl, - [Class, Fn, TsInterface, TsTypeAlias, TsEnum, TsModule, Var] -); - -diff_struct!(VarDecl, [span, kind, decls, declare]); -diff_struct!(VarDeclarator, [span, name, init, definite]); -diff_struct!(ClassDecl, [ident, class, declare]); -diff_struct!(FnDecl, [ident, function, declare]); - -diff_struct!( - Function, - [ - params, - decorators, - span, - body, - is_generator, - is_async, - type_params, - return_type - ] -); - -diff_struct!(Param, [span, decorators, pat]); -diff_struct!( - Class, - [ - span, - decorators, - body, - super_class, - is_abstract, - type_params, - super_type_params, - implements - ] -); -diff_enum!( - ClassMember, - [ - Constructor, - Method, - PrivateMethod, - ClassProp, - PrivateProp, - TsIndexSignature, - Empty, - StaticBlock - ] -); -diff_struct!( - Constructor, - [span, params, body, key, accessibility, is_optional] -); -diff_enum!(ParamOrTsParamProp, [Param, TsParamProp]); -diff_enum!( - ModuleDecl, - [ - Import, - ExportDecl, - ExportNamed, - ExportDefaultDecl, - ExportDefaultExpr, - ExportAll, - TsImportEquals, - TsExportAssignment, - TsNamespaceExport - ] -); -diff_struct!(StaticBlock, [span, body]); -diff_struct!( - ClassMethod, - [ - span, - key, - function, - kind, - is_static, - accessibility, - is_abstract, - is_optional, - is_override - ] -); -diff_struct!( - PrivateMethod, - [ - span, - key, - function, - kind, - is_static, - accessibility, - is_abstract, - is_optional, - is_override - ] -); -diff_struct!( - ClassProp, - [ - span, - key, - value, - type_ann, - is_static, - is_abstract, - is_optional, - is_override, - readonly, - accessibility, - decorators, - declare, - definite - ] -); -diff_struct!( - PrivateProp, - [ - span, - key, - value, - type_ann, - is_static, - is_abstract, - is_optional, - is_override, - readonly, - computed, - accessibility, - decorators, - definite - ] -); -diff_struct!(ImportDecl, [span, specifiers, src, type_only, asserts]); -diff_struct!(ExportDecl, [span, decl]); -diff_struct!(ExportDefaultDecl, [span, decl]); -diff_struct!(ExportDefaultExpr, [span, expr]); -diff_struct!(NamedExport, [span, specifiers, src, type_only, asserts]); -diff_struct!(ExportAll, [span, src, asserts]); -diff_enum!(ImportSpecifier, [Named, Default, Namespace]); -diff_enum!(ExportSpecifier, [Named, Default, Namespace]); -diff_enum!(DefaultDecl, [Class, Fn, TsInterfaceDecl]); -diff_enum!(ModuleExportName, [Ident, Str]); - -diff_struct!(ImportNamedSpecifier, [span, local, imported, is_type_only]); -diff_struct!(ImportDefaultSpecifier, [span, local]); -diff_struct!(ImportStarAsSpecifier, [span, local]); - -diff_struct!(ExportNamedSpecifier, [span, orig, exported, is_type_only]); -diff_struct!(ExportDefaultSpecifier, [exported]); -diff_struct!(ExportNamespaceSpecifier, [span, name]); diff --git a/crates/swc_ecma_diff/src/js_ast/typescript.rs b/crates/swc_ecma_diff/src/js_ast/typescript.rs deleted file mode 100644 index a5272ef7b51..00000000000 --- a/crates/swc_ecma_diff/src/js_ast/typescript.rs +++ /dev/null @@ -1,178 +0,0 @@ -use swc_ecma_ast::*; - -diff_struct!(TsTypeAnn, [span, type_ann]); -diff_struct!(TsTypeParamDecl, [span, params]); -diff_struct!(TsTypeParam, [span, name, constraint, default]); - -diff_enum!( - TsType, - [ - TsKeywordType, - TsThisType, - TsFnOrConstructorType, - TsTypeRef, - TsTypeQuery, - TsTypeLit, - TsArrayType, - TsTupleType, - TsOptionalType, - TsRestType, - TsUnionOrIntersectionType, - TsConditionalType, - TsInferType, - TsParenthesizedType, - TsTypeOperator, - TsIndexedAccessType, - TsMappedType, - TsLitType, - TsTypePredicate, - TsImportType - ] -); -diff_enum!(TsEntityName, [TsQualifiedName, Ident]); -diff_enum!( - TsTypeElement, - [ - TsCallSignatureDecl, - TsConstructSignatureDecl, - TsPropertySignature, - TsGetterSignature, - TsSetterSignature, - TsMethodSignature, - TsIndexSignature - ] -); - -diff_struct!(TsTypeParamInstantiation, [span, params]); -diff_struct!(TsExprWithTypeArgs, [span, expr, type_args]); -diff_struct!(TsAsExpr, [span, expr, type_ann]); -diff_struct!(TsTypeAssertion, [span, expr, type_ann]); -diff_struct!(TsConstAssertion, [span, expr]); -diff_struct!(TsNonNullExpr, [span, expr]); -diff_struct!( - TsInterfaceDecl, - [span, id, declare, type_params, extends, body] -); -diff_struct!(TsInterfaceBody, [span, body]); -diff_struct!(TsTypeAliasDecl, [span, declare, id, type_params, type_ann]); -diff_struct!(TsEnumDecl, [span, declare, id, members, is_const]); -diff_struct!(TsEnumMember, [span, id, init]); -diff_enum!(TsEnumMemberId, [Str, Ident]); -diff_struct!(TsModuleDecl, [span, id, body, declare, global]); -diff_enum!(TsModuleName, [Ident, Str]); -diff_enum!(TsNamespaceBody, [TsModuleBlock, TsNamespaceDecl]); -trivial!(Accessibility); -diff_struct!( - TsIndexSignature, - [params, type_ann, readonly, is_static, span] -); -diff_enum!(TsFnParam, [Ident, Array, Object, Rest]); -diff_struct!( - TsParamProp, - [ - span, - decorators, - accessibility, - is_override, - readonly, - param - ] -); -diff_enum!(TsParamPropParam, [Ident, Assign]); -diff_struct!( - TsImportEqualsDecl, - [span, declare, is_export, is_type_only, id, module_ref] -); -diff_enum!(TsModuleRef, [TsEntityName, TsExternalModuleRef]); -diff_struct!(TsExportAssignment, [span, expr]); -diff_struct!(TsNamespaceExportDecl, [id, span]); - -diff_struct!(TsKeywordType, [span, kind]); -trivial!(TsKeywordTypeKind); -diff_struct!(TsThisType, [span]); -diff_enum!(TsUnionOrIntersectionType, [TsUnionType, TsIntersectionType]); -diff_enum!(TsFnOrConstructorType, [TsFnType, TsConstructorType]); -diff_struct!(TsTypeRef, [span, type_name, type_params]); -diff_struct!(TsTypeQuery, [span, expr_name]); -diff_enum!(TsTypeQueryExpr, [TsEntityName, Import]); -diff_struct!(TsTypeLit, [span, members]); -diff_struct!(TsTupleType, [span, elem_types]); -diff_struct!(TsTupleElement, [span, label, ty]); -diff_struct!(TsArrayType, [span, elem_type]); -diff_struct!(TsOptionalType, [span, type_ann]); -diff_struct!(TsRestType, [span, type_ann]); -diff_struct!( - TsConditionalType, - [span, check_type, extends_type, true_type, false_type] -); -diff_struct!(TsInferType, [span, type_param]); -diff_struct!(TsParenthesizedType, [span, type_ann]); -diff_struct!(TsTypeOperator, [span, op, type_ann]); -diff_struct!(TsIndexedAccessType, [span, obj_type, index_type, readonly]); -diff_struct!( - TsMappedType, - [span, readonly, type_param, type_ann, name_type, optional] -); -diff_struct!(TsLitType, [span, lit]); -trivial!(TruePlusMinus); -diff_enum!(TsLit, [Number, Str, Bool, BigInt, Tpl]); -diff_struct!(TsTypePredicate, [span, param_name, asserts, type_ann]); -diff_enum!(TsThisTypeOrIdent, [TsThisType, Ident]); -diff_struct!(TsImportType, [span, arg, type_args, qualifier]); -diff_struct!(TsQualifiedName, [left, right]); -diff_struct!(TsUnionType, [span, types]); -diff_struct!(TsIntersectionType, [span, types]); -diff_struct!(TsFnType, [span, params, type_params, type_ann]); -diff_struct!( - TsConstructorType, - [span, params, type_params, type_ann, is_abstract] -); - -diff_struct!(TsCallSignatureDecl, [span, params, type_ann, type_params]); -diff_struct!( - TsConstructSignatureDecl, - [span, params, type_ann, type_params] -); -diff_struct!( - TsPropertySignature, - [ - span, - key, - type_ann, - optional, - readonly, - computed, - init, - params, - type_params - ] -); -diff_struct!( - TsMethodSignature, - [ - span, - key, - type_ann, - params, - type_params, - readonly, - computed, - optional - ] -); -diff_struct!( - TsGetterSignature, - [span, readonly, key, computed, optional, type_ann] -); -diff_struct!( - TsSetterSignature, - [span, readonly, key, computed, optional, param] -); - -diff_struct!(TsNamespaceDecl, [span, declare, global, id, body]); - -diff_struct!(TsModuleBlock, [span, body]); - -diff_struct!(TsExternalModuleRef, [span, expr]); - -diff_struct!(TsTplLitType, [span, types, quasis]); diff --git a/crates/swc_ecma_diff/src/lib.rs b/crates/swc_ecma_diff/src/lib.rs deleted file mode 100644 index b364f6526b2..00000000000 --- a/crates/swc_ecma_diff/src/lib.rs +++ /dev/null @@ -1,321 +0,0 @@ -pub use self::ctx::{Ctx, PathComponent}; -use std::fmt::{self, Debug, Display, Formatter}; -use swc_common::Span; - -#[macro_use] -mod macros; -mod ctx; -mod js_ast; - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub struct Config { - /// If this value is true, the differences of [Span]s are ignored. - /// - /// Defaults to false. - pub ignore_span: bool, -} - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub struct Node(String); - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub struct Difference { - pub path: Vec, - pub left: Node, - pub right: Node, -} - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub enum DiffResult { - /// Two nodes are identical. - Identical, - - Different(Difference), - - Multiple(Vec), -} - -impl From for DiffResult { - fn from(v: Difference) -> Self { - DiffResult::Different(v) - } -} - -impl Display for Difference { - fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { - write!(f, "Path: ")?; - for c in &self.path { - match c { - PathComponent::StructProp { struct_name, key } => { - write!( - f, - "({struct_name}.{key})", - key = key, - struct_name = struct_name - )?; - } - PathComponent::VecElem { l, r } => { - write!(f, "[{} <-> {}]", l, r)?; - } - } - } - writeln!(f)?; - - writeln!(f, "Left: {}", self.left.0)?; - writeln!(f, "Right: {}", self.right.0)?; - - Ok(()) - } -} - -impl Display for DiffResult { - fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { - match self { - DiffResult::Identical => {} - DiffResult::Different(d) => { - writeln!(f, "{}", d)?; - } - DiffResult::Multiple(d) => { - if d.len() == 1 { - for d in d { - write!(f, "{}", d)?; - } - } else { - for d in d { - writeln!(f, "{}", d)?; - } - } - } - } - - Ok(()) - } -} - -#[auto_impl::auto_impl(Box)] -pub trait Diff: Debug { - /// This may remove common node from `self` and `other`. - fn diff(&mut self, other: &mut Self, ctx: &mut Ctx) -> DiffResult; -} - -impl Diff for Span { - fn diff(&mut self, other: &mut Self, ctx: &mut Ctx) -> DiffResult { - if *self == *other { - return DiffResult::Identical; - } - - if ctx.config.ignore_span { - return DiffResult::Identical; - } - - DiffResult::Different(Difference { - path: ctx.path.clone(), - left: Node(format!("{:?}", self)), - right: Node(format!("{:?}", other)), - }) - } -} - -impl Diff for Vec -where - T: Diff, -{ - fn diff(&mut self, other: &mut Self, ctx: &mut Ctx) -> DiffResult { - let mut results = Vec::new(); - - if self.len() != other.len() { - results.push(DiffResult::Different(Difference { - path: ctx.path.clone(), - left: Node(format!("len = {}", self.len())), - right: Node(format!("len = {}", other.len())), - })); - } - - let mut should_retry = false; - - let should_try_shifting = ctx.path.iter().all(|v| match v { - PathComponent::VecElem { l, r } => *l == *r, - _ => true, - }); - - // If we are visiting this vector for the first time, we can shift indexes to - // reduce output files. - // - // e.g. - // - // A: - // - // console.log('Foo') - // console.log('Bar') - // console.log('Baz') - // - // - // B: - // - // console.log('Bar') - // console.log('Baz') - // - // - // We can remove two statements. - if should_try_shifting { - let mut l_removed = vec![]; - let mut r_removed = vec![]; - - for (l_idx, l) in self.iter_mut().enumerate() { - for (r_idx, r) in other.iter_mut().enumerate() { - if r_removed.contains(&r_idx) { - continue; - } - - let mut ctx = ctx.clone(); - ctx.path.push(PathComponent::VecElem { l: l_idx, r: r_idx }); - - let diff = l.diff(r, &mut ctx); - - if matches!(diff, DiffResult::Identical) { - l_removed.push(l_idx); - r_removed.push(r_idx); - should_retry = true; - break; - } - if l_idx == r_idx { - results.push(diff); - } - } - } - - if !l_removed.is_empty() { - let new_l = self - .drain(..) - .enumerate() - .filter(|(i, _)| !l_removed.contains(i)) - .map(|(_, v)| v) - .collect::>(); - - *self = new_l; - } - - if !r_removed.is_empty() { - let new_r = other - .drain(..) - .enumerate() - .filter(|(i, _)| !r_removed.contains(i)) - .map(|(_, v)| v) - .collect::>(); - *other = new_r; - } - } else { - let mut l = self.iter_mut(); - let mut r = other.iter_mut(); - let mut idx = 0; - let mut removed = vec![]; - - while let (Some(l), Some(r)) = (l.next(), r.next()) { - let cur_idx = idx; - idx += 1; - - let mut ctx = ctx.clone(); - ctx.path.push(PathComponent::VecElem { - l: cur_idx, - r: cur_idx, - }); - - let diff = l.diff(r, &mut ctx); - - if matches!(diff, DiffResult::Identical) { - removed.push(cur_idx); - continue; - } - - results.push(diff); - } - - if !removed.is_empty() { - should_retry = true; - - let new_l = self - .drain(..) - .enumerate() - .filter(|(i, _)| !removed.contains(i)) - .map(|(_, v)| v) - .collect::>(); - let new_r = other - .drain(..) - .enumerate() - .filter(|(i, _)| !removed.contains(i)) - .map(|(_, v)| v) - .collect::>(); - - *self = new_l; - *other = new_r; - } - } - - if should_retry { - return self.diff(other, ctx); - } - - // TODO: Dump extra nodes - - if results.is_empty() { - return DiffResult::Identical; - } - - DiffResult::Multiple(results) - } -} - -impl Diff for Option -where - T: Diff, -{ - fn diff(&mut self, other: &mut Self, ctx: &mut Ctx) -> DiffResult { - let result = match (&mut *self, &mut *other) { - (Some(l), Some(r)) => l.diff(r, ctx), - (None, None) => DiffResult::Identical, - (None, Some(r)) => DiffResult::Different(Difference { - path: ctx.path.clone(), - left: Node("None".into()), - right: Node(format!("{:?}", r)), - }), - (Some(l), None) => DiffResult::Different(Difference { - path: ctx.path.clone(), - left: Node(format!("{:?}", l)), - right: Node("None".into()), - }), - }; - - if matches!(result, DiffResult::Identical) { - // Remove common node. - *self = None; - *other = None; - return result; - } - - result - } -} - -trivial!(bool, (), char); -trivial!(usize, u8, u16, u32, u64, u128); -trivial!(isize, i8, i16, i32, i64, i128); -trivial!(f32, f64); -trivial!(String, str); -trivial!(num_bigint::BigInt); - -impl Diff for string_cache::Atom -where - S: string_cache::StaticAtomSet, -{ - fn diff(&mut self, other: &mut Self, ctx: &mut Ctx) -> DiffResult { - if *self == *other { - return DiffResult::Identical; - } - - DiffResult::Different(Difference { - path: ctx.path.clone(), - left: Node(format!("{:?}", self)), - right: Node(format!("{:?}", other)), - }) - } -} diff --git a/crates/swc_ecma_diff/src/macros.rs b/crates/swc_ecma_diff/src/macros.rs deleted file mode 100644 index 424e522ed2c..00000000000 --- a/crates/swc_ecma_diff/src/macros.rs +++ /dev/null @@ -1,108 +0,0 @@ -macro_rules! trivial { - ($T:ty) => { - impl crate::Diff for $T { - fn diff(&mut self, other: &mut Self, ctx: &mut crate::Ctx) -> crate::DiffResult { - if *self == *other { - return crate::DiffResult::Identical; - } - - crate::DiffResult::Different(crate::Difference { - path: ctx.path.clone(), - left: crate::Node(format!("{:?}", self)), - right: crate::Node(format!("{:?}", other)), - }) - } - } - }; - - ( - $T:ty, $($tt:tt)* - ) => { - trivial!($T); - trivial!($($tt)*); - }; -} - -macro_rules! diff_struct { - ( - $T:ident, - [ - $($field:ident),* - ] - ) => { - impl crate::Diff for $T { - fn diff(&mut self, other: &mut Self, ctx: &mut crate::Ctx) -> crate::DiffResult { - // Ensure that we diff all fields. - #[allow(unused)] - fn _assert_all_fields(_node: &$T){ - let $T { - $($field,)* - } = _node; - } - use swc_common::EqIgnoreSpan; - - - let result = ctx.diff_struct(stringify!($T), |ctx| { - - $( - ctx.field(stringify!($field), &mut self.$field, &mut other.$field); - )* - }); - - if ctx.config.ignore_span{ - if self.eq_ignore_span(&*other) { - return crate::DiffResult::Identical; - } - } else { - if *self == *other { - return crate::DiffResult::Identical; - } - } - - result - } - } - }; -} - -macro_rules! diff_enum { - ( - $T:ident, - [ - $($Variant:ident),* - ] - ) => { - impl crate::Diff for $T { - fn diff(&mut self, other: &mut Self, ctx: &mut crate::Ctx) -> crate::DiffResult { - // Ensure that we handle all variants. - fn _assert_all_variants(_node: &$T){ - match _node { - $( - $T::$Variant(..) => {}, - )* - } - } - - match (&mut *self, &mut * other) { - $( - ( - $T::$Variant(l), - $T::$Variant(r), - ) => crate::Diff::diff(l,r,ctx), - )* - _ => crate::DiffResult::Different(crate::Difference { - path: ctx.path.clone(), - left: crate::Node(format!("{:?}", self)), - right: crate::Node(format!("{:?}", other)), - }), - } - } - } - }; -} - -macro_rules! diff_string_enum { - ($T:ty) => { - trivial!($T); - }; -} diff --git a/crates/swc_ecma_diff/tests/diff/1/l.js b/crates/swc_ecma_diff/tests/diff/1/l.js deleted file mode 100644 index 835fc994ebe..00000000000 --- a/crates/swc_ecma_diff/tests/diff/1/l.js +++ /dev/null @@ -1,4 +0,0 @@ -import foo from 'foo;' - -console.log(foo); -console.log(foo); \ No newline at end of file diff --git a/crates/swc_ecma_diff/tests/diff/1/l.output.js b/crates/swc_ecma_diff/tests/diff/1/l.output.js deleted file mode 100644 index 88cce3dfecd..00000000000 --- a/crates/swc_ecma_diff/tests/diff/1/l.output.js +++ /dev/null @@ -1 +0,0 @@ -console.log(foo); diff --git a/crates/swc_ecma_diff/tests/diff/1/output.swc-diff b/crates/swc_ecma_diff/tests/diff/1/output.swc-diff deleted file mode 100644 index 3eaabe6e260..00000000000 --- a/crates/swc_ecma_diff/tests/diff/1/output.swc-diff +++ /dev/null @@ -1,4 +0,0 @@ -Path: (Module.body) -Left: len = 1 -Right: len = 0 - diff --git a/crates/swc_ecma_diff/tests/diff/1/r.js b/crates/swc_ecma_diff/tests/diff/1/r.js deleted file mode 100644 index 62cd11f0ca8..00000000000 --- a/crates/swc_ecma_diff/tests/diff/1/r.js +++ /dev/null @@ -1,3 +0,0 @@ -import foo from 'foo;' - -console.log(foo); \ No newline at end of file diff --git a/crates/swc_ecma_diff/tests/diff/2/l.js b/crates/swc_ecma_diff/tests/diff/2/l.js deleted file mode 100644 index 52833ac02e9..00000000000 --- a/crates/swc_ecma_diff/tests/diff/2/l.js +++ /dev/null @@ -1,3 +0,0 @@ -console.log('Foo') -console.log('Bar') -console.log('Baz') \ No newline at end of file diff --git a/crates/swc_ecma_diff/tests/diff/2/l.output.js b/crates/swc_ecma_diff/tests/diff/2/l.output.js deleted file mode 100644 index b6ccd87de89..00000000000 --- a/crates/swc_ecma_diff/tests/diff/2/l.output.js +++ /dev/null @@ -1 +0,0 @@ -console.log('Foo'); diff --git a/crates/swc_ecma_diff/tests/diff/2/output.swc-diff b/crates/swc_ecma_diff/tests/diff/2/output.swc-diff deleted file mode 100644 index 3eaabe6e260..00000000000 --- a/crates/swc_ecma_diff/tests/diff/2/output.swc-diff +++ /dev/null @@ -1,4 +0,0 @@ -Path: (Module.body) -Left: len = 1 -Right: len = 0 - diff --git a/crates/swc_ecma_diff/tests/diff/2/r.js b/crates/swc_ecma_diff/tests/diff/2/r.js deleted file mode 100644 index 8b1b2ac9cf1..00000000000 --- a/crates/swc_ecma_diff/tests/diff/2/r.js +++ /dev/null @@ -1,2 +0,0 @@ -console.log('Bar') -console.log('Baz') \ No newline at end of file diff --git a/crates/swc_ecma_diff/tests/fixture.rs b/crates/swc_ecma_diff/tests/fixture.rs deleted file mode 100644 index ca908fe9d77..00000000000 --- a/crates/swc_ecma_diff/tests/fixture.rs +++ /dev/null @@ -1,81 +0,0 @@ -use std::path::{Path, PathBuf}; -use swc_common::{input::SourceFileInput, sync::Lrc, SourceMap}; -use swc_ecma_ast::Module; -use swc_ecma_codegen::{ - text_writer::{JsWriter, WriteJs}, - Emitter, -}; -use swc_ecma_diff::{Config, Ctx, Diff}; -use swc_ecma_parser::{lexer::Lexer, EsConfig, Parser, Syntax}; -use testing::NormalizedOutput; - -fn parse(cm: Lrc, path: &Path) -> Module { - let fm = cm.load_file(path).unwrap(); - - let lexer = Lexer::new( - Syntax::Es(EsConfig { - jsx: true, - ..Default::default() - }), - Default::default(), - SourceFileInput::from(&*fm), - None, - ); - - let mut parser = Parser::new_from(lexer); - - parser.parse_module().unwrap() -} - -#[testing::fixture("tests/diff/**/l.js")] -fn diff(l: PathBuf) { - let r = l.with_file_name("r.js"); - let spec = l.with_file_name("output.swc-diff"); - - let (diff_str, l_str, r_str) = testing::run_test(false, |cm, _handler| { - let mut l = parse(cm.clone(), &l); - let mut r = parse(cm.clone(), &r); - - let mut ctx = Ctx::new(Config { ignore_span: true }); - let res = l.diff(&mut r, &mut ctx); - - let l = print(cm.clone(), &[l]); - let r = print(cm, &[r]); - - Ok((format!("{}", res), l, r)) - }) - .unwrap(); - - NormalizedOutput::from(l_str) - .compare_to_file(&l.with_file_name("l.output.js")) - .unwrap(); - - NormalizedOutput::from(r_str) - .compare_to_file(&r.with_file_name("r.output.js")) - .unwrap(); - - NormalizedOutput::from(diff_str) - .compare_to_file(&spec) - .unwrap(); -} - -fn print(cm: Lrc, nodes: &[N]) -> String { - let mut buf = vec![]; - - { - let wr: Box = Box::new(JsWriter::new(cm.clone(), "\n", &mut buf, None)); - - let mut emitter = Emitter { - cfg: swc_ecma_codegen::Config { minify: false }, - cm, - comments: None, - wr, - }; - - for n in nodes { - n.emit_with(&mut emitter).unwrap(); - } - } - - String::from_utf8(buf).unwrap() -}