From 8af568f8ead99dfa8fdcd811f8ff370fbde7e0cc Mon Sep 17 00:00:00 2001 From: mantou132 <709922234@qq.com> Date: Tue, 26 Nov 2024 22:07:18 +0800 Subject: [PATCH] [swc] Improve import --- Cargo.lock | 13 ++++++++--- Cargo.toml | 1 + crates/swc-plugin-gem/Cargo.toml | 1 + crates/swc-plugin-gem/package.json | 2 +- crates/swc-plugin-gem/src/lib.rs | 3 +++ crates/swc-plugin-gem/src/visitors/import.rs | 23 ++++++++++++++++--- crates/swc-plugin-gem/src/visitors/memo.rs | 13 +++++++++++ .../fixture/auto-import/elements/input.ts | 1 + .../fixture/auto-import/elements/output.ts | 8 ++++--- .../fixture/auto-import/members/output.ts | 2 +- .../tests/fixture/memo/input.ts | 15 ++++++++++-- .../tests/fixture/memo/output.ts | 15 +++++++++++- .../tests/fixture/path/output.ts | 4 ++-- 13 files changed, 85 insertions(+), 16 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d97d7592..10ef754b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -704,6 +704,12 @@ dependencies = [ "allocator-api2", ] +[[package]] +name = "hashbrown" +version = "0.15.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" + [[package]] name = "heck" version = "0.4.1" @@ -881,12 +887,12 @@ checksum = "cb56e1aa765b4b4f3aadfab769793b7087bb03a4ea4920644a6d238e2df5b9ed" [[package]] name = "indexmap" -version = "2.5.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68b900aa2f7301e21c36462b170ee99994de34dff39a4a6a528e80e7376d07e5" +checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" dependencies = [ "equivalent", - "hashbrown 0.14.5", + "hashbrown 0.15.2", "serde", ] @@ -2303,6 +2309,7 @@ dependencies = [ name = "swc_plugin_gem" version = "0.1.0" dependencies = [ + "indexmap", "once_cell", "regex", "serde", diff --git a/Cargo.toml b/Cargo.toml index cdb8adad..2533fdc0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,6 +12,7 @@ license = "Apache-2.0" repository = "https://github.com/mantou132/gem.git" [workspace.dependencies] +indexmap = { version = "2.6.0" } regex = { version = "1.10.4", default-features = false } serde = "1.0.203" serde_json = "1.0.117" diff --git a/crates/swc-plugin-gem/Cargo.toml b/crates/swc-plugin-gem/Cargo.toml index d6071c18..60a50b58 100644 --- a/crates/swc-plugin-gem/Cargo.toml +++ b/crates/swc-plugin-gem/Cargo.toml @@ -21,6 +21,7 @@ swc_ecma_ast = { workspace = true } once_cell = { workspace = true } tracing = { workspace = true } regex = { workspace = true } +indexmap = { workspace = true, features = ["serde"] } [dev-dependencies] swc_ecma_parser = { workspace = true } diff --git a/crates/swc-plugin-gem/package.json b/crates/swc-plugin-gem/package.json index 90e02e5b..d97272cd 100644 --- a/crates/swc-plugin-gem/package.json +++ b/crates/swc-plugin-gem/package.json @@ -1,6 +1,6 @@ { "name": "swc-plugin-gem", - "version": "0.1.1", + "version": "0.1.2", "description": "swc plugin for Gem", "keywords": [ "swc-plugin", diff --git a/crates/swc-plugin-gem/src/lib.rs b/crates/swc-plugin-gem/src/lib.rs index d6f08983..07e20cb8 100644 --- a/crates/swc-plugin-gem/src/lib.rs +++ b/crates/swc-plugin-gem/src/lib.rs @@ -1,6 +1,7 @@ use serde::Deserialize; use swc_common::pass::Optional; use swc_core::ecma::visit::VisitMutWith; +use swc_core::plugin::metadata::TransformPluginMetadataContextKind; use swc_core::plugin::{plugin_transform, proxies::TransformPluginProgramMetadata}; use swc_ecma_ast::Program; use visitors::import::gen_once_dts; @@ -35,6 +36,8 @@ pub fn process_transform(mut program: Program, data: TransformPluginProgramMetad let config = serde_json::from_str::(plugin_config).expect("invalid config for gem plugin"); + let _file_name = data.get_context(&TransformPluginMetadataContextKind::Filename); + // 执行在每个文件 if config.auto_import_dts { gen_once_dts(); diff --git a/crates/swc-plugin-gem/src/visitors/import.rs b/crates/swc-plugin-gem/src/visitors/import.rs index 08b3d2e2..2045f7ea 100644 --- a/crates/swc-plugin-gem/src/visitors/import.rs +++ b/crates/swc-plugin-gem/src/visitors/import.rs @@ -1,8 +1,9 @@ +use indexmap::IndexMap; use once_cell::sync::Lazy; use regex::Regex; use serde::Deserialize; use std::{ - collections::{BTreeMap, HashMap, HashSet}, + collections::{HashMap, HashSet}, fs, path::Path, }; @@ -27,7 +28,7 @@ enum MemberOrMemberAs { #[serde(rename_all = "camelCase")] struct AutoImportContent { members: HashMap>, - elements: HashMap>, + elements: IndexMap>, } struct AutoImportConfig { @@ -157,7 +158,7 @@ impl VisitMut for TransformVisitor { node.visit_mut_children_with(self); let mut out: Vec = vec![]; - let mut available_import: HashMap> = HashMap::new(); + let mut available_import: HashMap> = HashMap::new(); for used_member in self.used_members.iter() { if !self.defined_members.contains(used_member) { @@ -203,6 +204,7 @@ impl VisitMut for TransformVisitor { with: None, phase: Default::default(), }); + break; } } } @@ -252,3 +254,18 @@ pub fn gen_once_dts() { ) .expect("create dts error"); } + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn should_return_default_config() { + let content: &str = include_str!("../auto-import.json"); + let config = serde_json::from_str::(content).unwrap(); + assert_eq!( + format!("{:?}", config.elements.get("duoyun-ui").unwrap().keys()), + r#"["dy-pat-*", "dy-input-*", "dy-*"]"# + ) + } +} diff --git a/crates/swc-plugin-gem/src/visitors/memo.rs b/crates/swc-plugin-gem/src/visitors/memo.rs index 6f026abe..2a179a1d 100644 --- a/crates/swc-plugin-gem/src/visitors/memo.rs +++ b/crates/swc-plugin-gem/src/visitors/memo.rs @@ -20,6 +20,11 @@ impl TransformVisitor { self.private_props.get(self.current_index).unwrap() } + fn start_visit_mut_class(&mut self) { + self.private_props = Vec::new(); + self.current_index = 0; + } + fn visit_mut_class(&mut self, node: &mut Box) { for prop in self.private_props.iter() { node.body.push(ClassMember::PrivateProp(PrivateProp { @@ -54,12 +59,16 @@ impl VisitMut for TransformVisitor { noop_visit_mut_type!(); fn visit_mut_class_decl(&mut self, node: &mut ClassDecl) { + self.start_visit_mut_class(); + node.visit_mut_children_with(self); self.visit_mut_class(&mut node.class); } fn visit_mut_class_expr(&mut self, node: &mut ClassExpr) { + self.start_visit_mut_class(); + node.visit_mut_children_with(self); self.visit_mut_class(&mut node.class); @@ -80,6 +89,10 @@ impl VisitMut for TransformVisitor { } fn visit_mut_return_stmt(&mut self, node: &mut ReturnStmt) { + // why? 类表达式会直接走到这里来? + if self.private_props.is_empty() { + return; + } node.arg = Some(Box::new(Expr::Assign(AssignExpr { span: DUMMY_SP, op: AssignOp::Assign, diff --git a/crates/swc-plugin-gem/tests/fixture/auto-import/elements/input.ts b/crates/swc-plugin-gem/tests/fixture/auto-import/elements/input.ts index 034dd1ec..a41d2cb7 100644 --- a/crates/swc-plugin-gem/tests/fixture/auto-import/elements/input.ts +++ b/crates/swc-plugin-gem/tests/fixture/auto-import/elements/input.ts @@ -4,6 +4,7 @@ export class MyElement extends GemElement { render() { return html` + ${html``} `; } diff --git a/crates/swc-plugin-gem/tests/fixture/auto-import/elements/output.ts b/crates/swc-plugin-gem/tests/fixture/auto-import/elements/output.ts index e1b8b7e4..8040f5e6 100644 --- a/crates/swc-plugin-gem/tests/fixture/auto-import/elements/output.ts +++ b/crates/swc-plugin-gem/tests/fixture/auto-import/elements/output.ts @@ -1,11 +1,13 @@ // @ts-nocheck -import { GemElement, html } from "@mantou/gem"; -import "@mantou/gem/elements/link" -import "duoyun-ui/elements/use" +import { html, GemElement } from "@mantou/gem"; +import "@mantou/gem/elements/link"; +import "duoyun-ui/elements/use"; +import "duoyun-ui/patterns/console"; export class MyElement extends GemElement { render() { return html` + ${html``} `; } diff --git a/crates/swc-plugin-gem/tests/fixture/auto-import/members/output.ts b/crates/swc-plugin-gem/tests/fixture/auto-import/members/output.ts index daf2a41c..ea60a8e8 100644 --- a/crates/swc-plugin-gem/tests/fixture/auto-import/members/output.ts +++ b/crates/swc-plugin-gem/tests/fixture/auto-import/members/output.ts @@ -1,5 +1,5 @@ // @ts-nocheck -import { adoptedStyle, attribute, css, customElement, emitter, html, styleMap, template } from "@mantou/gem"; +import { css, adoptedStyle, customElement, attribute, emitter, template, styleMap, html } from "@mantou/gem"; import { render, Emitter, GemElement } from '@mantou/gem'; const style = css``; @adoptedStyle(style) diff --git a/crates/swc-plugin-gem/tests/fixture/memo/input.ts b/crates/swc-plugin-gem/tests/fixture/memo/input.ts index 8f2e47fd..0f387804 100644 --- a/crates/swc-plugin-gem/tests/fixture/memo/input.ts +++ b/crates/swc-plugin-gem/tests/fixture/memo/input.ts @@ -1,8 +1,19 @@ // @ts-nocheck - -class MyElement { +class MyElement {} +class MyElement1 { @memo(['src']) get #src() { + if (bool) return '#src'; return '#src'; } } +class MyElement2 { + get #src() { + if (bool) return '#src'; + return '#src'; + } + @memo(['src']) + get #src2() { + return '#src'; + } +} \ No newline at end of file diff --git a/crates/swc-plugin-gem/tests/fixture/memo/output.ts b/crates/swc-plugin-gem/tests/fixture/memo/output.ts index 5d54fe6e..95c9421b 100644 --- a/crates/swc-plugin-gem/tests/fixture/memo/output.ts +++ b/crates/swc-plugin-gem/tests/fixture/memo/output.ts @@ -1,9 +1,22 @@ // @ts-nocheck -class MyElement { +class MyElement {} +class MyElement1 { @memo(['src']) get #_src() { + if (bool) return this.#src = '#src'; return this.#src = '#src'; } #src; } +class MyElement2 { + get #src() { + if (bool) return '#src'; + return '#src'; + } + @memo(['src']) + get #_src2() { + return this.#src2 = '#src'; + } + #src2; +} \ No newline at end of file diff --git a/crates/swc-plugin-gem/tests/fixture/path/output.ts b/crates/swc-plugin-gem/tests/fixture/path/output.ts index 1dcbdb6b..0af3c23d 100644 --- a/crates/swc-plugin-gem/tests/fixture/path/output.ts +++ b/crates/swc-plugin-gem/tests/fixture/path/output.ts @@ -1,3 +1,3 @@ // @ts-nocheck -import '@mantou/gem/index.js'; -import '@mantou/gem/helper/react-shim.js'; +import "@mantou/gem.js"; +import "@mantou/gem/helper/react-shim.js";